# 这是注释
'content'
,双引号"content"
都可以*
重复,+
拼接'a'*3+'b'
'py' 'thon'
a, b = 1, 'a'
l = [1, "a"]或l=(1, "a")
a, b = l
一个python文件
就是一个模块
# 获取当前模块的
dir()
# 获取指定模块的
import m
dir(m)
# 模块名
__name__
# 模块文件的绝对路径
__file__
# 模块所在的包
__package__
# 命令
python m.py <args>
# 注意:这样执行时m.py的__name__为__main__
# 如果只是导入的话
import m
print(m.__name__) # 为m
# 因此如果要在测试模块内容,可以在模块内添加
if __name__ == "__main__":
#code
# 这样在别的模块import时,不会执行这些测试代码
包是一个目录,该目录必须有一个__init__.py
文件
sys.path
中注意
: 出于效率的考虑,每个模块在每个解释器会话中只被导入一次
。因此,如果你更改了你的模块,则必须重新启动解释器, 或者,如果它只是一个要交互式地测试的模块,使用importlib.reload(modulename)
。# 导入模块
import mod
mod.func()
# 从包中导入模块
import pkg.mod
pkg.mod.func()
# 更方便的方法
from pkg import mod
mod.func()
# 导入指定函数
from mod import func
func()
# 从包中导入*
# 需要在包的__init__.py文件中指定
__all__ = ["Mod1"]
# 这样
from pkg import *
# 会导入Mod1模块
# 可以使用相对引用
from .. import Mod1
https://docs.python.org/zh-cn/3.8/tutorial/controlflow.html
def f1():
"""
基本函数定义
:return: 返回Hello
"""
return "hello"
def f2(a, b=1):
"""
带默认值的函数
:param a: 参数a
:param b: 参数b的默认值为1
:return: 返回a+b
"""
return a+b
def f3(*args, **kvs):
"""
不定参数
:param args:不定参数,即tuple
:param kvs:不定键值对,即dict
"""
print("f3:")
print("args:", args)
print("kvs:", kvs)
f3("arg1", "arg2", k1="v1", k2="v2")
在/
前面强制为位置参数,调用时不能添加关键字,在*
后面的强制为关键字参数,调用时必须添加关键字,其他的不进行限制
def f4(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
"""
关键字或位置参数
"""
pass
f4(1,2,3,kwd1=4,kwd2=5)
def f5(*args, a, b):
"""
解包参数列表
"""
print("f5:")
print(args)
print(a)
print(b)
tp = (1, 2, 3)
dt = {
"a": 1, "b": 2}
f5(*tp, **dt)
def f6(n):
"""
返回lambda表达式构成的匿名函数
"""
return lambda x: x + n
# 上面语句相当于下面的
# def ff(x):
# return n+x
# return ff
print("f6:", f6(42)(5))
指定具体类型
,调用时类型不对时将会获得警告
,但不会出错
def f7(a: int, b: str) -> list:
"""
函数标注
:rtype: list值
:param a: int值
:param b: str值
:return: 返回list
"""
return [a, b]
print("f7:", f7(2, 'a'))
# 空的
l = []
l = list()
# 有初始数据
l = [1,"a"]
l = list([1,"a"])
l[0]
l.append(2)
l[0] = 2
l.insert(0,2)
del l[0]
#移除列表中某个值的第一个匹配
l.remove('a')
#弹出,默认index=-1(最后一个元素)
l.pop(index)
#列表元素个数
len(l)
#列表元素最大值
max(l)
#列表元素最小值
min(l)
#统计某个元素在列表中出现的次数
l.count('a')
#在列表末尾一次性追加多个值
l.extend([1,2,3])
#某个元素在列表中的第一个索引
l.index('a')
#列表反向
l.reverse()
#清空
l.clear()
#复制
l.copy()
与List类似,但其中的元素不可变
,不可修改
,不可删除
# 括号可以加上或省略
t = 1,
t = (1,)
t = 1,'a'
t = (1,'a')
t[0]
t = (1,) + ('a',)
t = (1,[])
t[1]可变
# 空的
s = set()
# 有初始值
s = {
1,'a'}
s = set((1,'a'))
# 基本数据类型
s.add(1)
s.add('a')
# 集合类型
s.update([2,3])
# 存在则删除,不存在则报错
s.remove('a')
# 存在则删除,不存在不报错
s.discard('a')
# 随机删除一个元素
s.pop()
# 差集
s1 - s2
# 并集
s1 | s2
# 交集
s1 & s2
# 两个集合不重复的,即交集-并集
s1 ^ s2
使用 | 解释 |
---|---|
s.clear() | 清空 |
s1.difference(s2) | s1-s2 |
s1.difference_update(s2) | s1 = s1-s2 |
s1.intersection(s2) | s1&s2 |
s1.intersection_update(s2) | s1 = s1&s2 |
s1.isdisjoint(s2) | 是否包含相同的元素 |
s1.issubset(s2) | s1是否为s2的子集 |
s1.issuperset(s2) | s1是否为s2的父集 |
s1.union(s2) | s1 |
s1.symmetric_difference(s2) | s1和s2不重复的元素 |
s1.symmetric_difference_update(s2) | s1=s1和s2不重复的元素 |
#空的
d = {
}
d = dict()
# 有初始值
d = {
1:'a',2:'a'}
# 从序列初始化
d = dict.fromkeys([1,2],'a')
# 按key,不存在则报错
d['a']
# 使用get
d.get('a',default=None)
# 直接添加或更新
d[1] = 'c'
# 如果存在key则不变,否则添加
d.setdefault(1,'a')
# 批量添加或更新
d1.update(d2)
# 直接删除,不存在此key则报错
del d['a']
# 删除,并返回值,不存在此key则报错
d.pop('a')
# 随机删除,并返回键值对
d.popitem()
函数 | 解释 |
---|---|
d.clear() | 清空 |
d.copy() | 复制 |
d.values() | 值序列(类型为dict_values),可以解包生成List,Set或Tuple |
d.keys() | 键序列,同上 |
d.items() | 键值对序列,同上 |
‘a’ in d或d.has_key(‘a’) | key是否在dic中(不要使用’a’ in d.keys()) |
l = ['a','b','c','d','e','f','g','h','i']
#第一个元素索引是0,倒数第一个元素索引是-1.
#取前5个元素
l[:5]
#取第3个到第五个元素
l[2,5]
#前5个,每2个取一个
l[:5:2]
#取后5个
l[-5:]
#后5个,每2个取1个
l[-5::2]
new = [exp(i) for i in old if filter_exp(i)]
exp(i) 关于i的表达式
filter_exp(i) 过滤某些值
# 1到30的偶数组成的list
l = [x for x in range(1, 31) if x % 2 == 0]
# 1到30的奇数组成的Set
s = {
x for x in range(1, 31) if x % 2 == 1}
# 键值对互换
d1 = {
'a': 10, 'b': 34}
d2 = {
v: k for k, v in d1.items()}
for v in l
for i in range(len(l))
for i,v in enumerate(l)
for v in s
for i,v in enumerate(s)
for k in d
for kv in d.items()
for k,v in d.items()
# 同时遍历多个序列,元素需要一一匹配时,使用zip函数
questions = ['name', 'quest', 'favorite color']
answers = ['lancelot', 'the holy grail', 'blue']
for q, a in zip(questions, answers):
print('What is your {0}? It is {1}.'.format(q, a))
#逆向循环一个序列,使用reversed函数
for v in reversed([1,2,3]):
#遍历一个排序后的序列
for v in sorted(...)
#循环时修改内容,可以创建一个新的序列,这样简单和安全
排序指南
sort
或sorted
#sort直接在原序列排序
#sorted可以排序任意可迭代对象,生成新的序列
l.sort(key,reverse)
l2 = sorted(iter,key,reverse)
Optional[Callable[[_T], Any]]
,即一个函数,参数为l
的元素,返回Any
# key需要一个函数,这里使用lambda匿名函数
l = ['a', 'aaa', 'aa']
l.sort(key=lambda x: len(x), reverse=True)
# 也可以直接指定函数
l.sort(key=str.lower)
l.sort(key=methodcaller('lower'))
# 如果每个元素都是元组,按照元组的第二个元素排
l.sort(key=lambda t:t[1])
l.sort(key=itemgetter(1))
# 如果每个元素都是对象,按照对象的属性排
students.sort(key=lambda student:student.age)
students.sort(key=attrgetter("age"))
#多关键字排序:
sorted(student_objects, key=attrgetter('grade', 'age'))
sorted(list, key=itemgetter(0,1))
#复杂排序:如先升序后降序,排序两次
s = sorted(student_objects, key=attrgetter('age'))
sorted(s, key=attrgetter('grade'), reverse=True)
输入输出
字符串参考指南
# 在字符串字面量中使用表达式
a=1
b='hello'
print(f"{a},{b}")
# 表达式中可以对变量格式化处理
f"{math.pi:.3f}" #保留3位小数
# 最小字符宽度
f"{name:10}" #最小宽度为10
# 对变量调用函数格式化
f"{name!s}"
# !s 为str()
# !r 为repr()
# !a 为ascii()
str.format()
>>> print('The story of {0}, {1}, and {other}.'.format('Bill', 'Manfred',other='Georg'))
The story of Bill, Manfred, and Georg.
>>> table = {
'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
>>> print('Jack: {Jack:d}; Sjoerd: {Sjoerd:d}; Dcab: {Dcab:d}'.format(**table))
Jack: 4098; Sjoerd: 4127; Dcab: 8637678
str()
# 将变量用字符串表示
a = 'hello'
str(a) # 字符串hello
repr()
# 将变量用字符串表示,并加上引号
a = 'hello'
repr(a) # 字符串`hello`
def read_file():
with open("testFile") as f:
for line in f:
f.readlines()
print(line)
def write_file():
with open("testFile", 'a') as f:
f.write("str\r\n")
'r' 只读
'w' 覆盖写
'x' 创建写
'a' 追加
# 1.f.read(n) 一次性读取n个字符
# 2.f.readline(limit) 一次性读一行的limit个字符
# 3.f.readlines() 一次性读全部的行存为list到内存
for line in f
与for line in f.readlines()
# for line in f 这是python推荐的,内存高效的,快速的,可以读大文件,python会自动管理内存
# for line in f.readlines() 不能读大文件,readlines会读全部内容到内存
todo:等了解第三方库后再更新这里
def divide(x, y):
try:
result = x / y
except ZeroDivisionError as err:
print(f"ZeroDivisionError:{err}")
except ValueError:
print("value err")
except Exception :
print("other err")
else:
print("result is", result)
finally:
print("executing finally clause")
class InputError(Exception):
def __init__(self, expression, message):
self.expression = expression
self.message = message
# 抛出异常
raise InputError
# 面向对象
import abc
from enum import Enum, unique
@unique # unique确保无重复值
class Weekday(Enum):
"""
枚举类
"""
# 左边为name,右边为value
Sun = 0
Mon = 1
Tue = 2
Wed = 3
Thu = 4
Fri = 5
Sat = 6
class Person(metaclass=abc.ABCMeta):
"""
Person 为抽象类,Person的子类需要实现抽象方法
"""
@abc.abstractmethod
def abs_m(self):
print("Person:abs_m")
class Student(Person):
"""
Student Doc
"""
# 实现抽象方法
def abs_m(self):
print("absMethod")
# 使用父类引用
def sup(self):
super().abs_m()
# count为类属性
count = 0
# 类方法
@classmethod
def cm(cls):
print("classMethod:", Student.count)
# 静态方法
@staticmethod
def sm():
print("staticMethod:", Student.count)
# 实例私有方法
def __p(self):
# 如果没有使用到self,这里可能会警告this method may be static
print("私有方法", self)
# 定义该类只允许有这些属性
__slots__ = ('name', '__age', "_gender")
def __init__(self, name, age, gender):
# 这是实例属性,外部可以直接访问
self.name = name
# 两个下划线开头是私有属性,在外部不能访问(如果要强行访问,可以使用s._Student__name,但不建议这样做)
self.__age = age
# 一个下划线开头也表示私有属性,在外部可以直接访问,但不建议访问(为什么这样设计?)
self._gender = gender
pass
# 双下划线开头和结尾的是特殊方法或变量,不是私有的,外部可以访问
# 因此不要把方法或属性名定义为双下划线开头和结尾
def __str__(self):
return f"{self.name}, {self.__age}, {self._gender}"
if __name__ == '__main__':
s = Student("jack", 12, "male")
# s的具体类型
print(type(s).__name__)
# 内置attr函数使用
print(hasattr(s, "name"))
print(getattr(s, "name"))
# print(delattr(s, "name"))
# print(setattr(s, "abc", 1))
# s是否是某个类型
print(isinstance(s, Student))
# Student类是否是某个类的子类
print(issubclass(Student, object))
# 调用s.__str__()方法
print(s)
# 使用枚举类
day = Weekday.Mon
print(day.name)
print(day.value)
from urllib import request
import http.client
if __name__ == '__main__':
with request.urlopen('http://www.baidu.com') as resp: # type:http.client.HTTPResponse
print(resp.readlines())
https://www.jetbrains.com/help/pycharm/2017.1/type-hinting-in-pycharm.html
# 3种方法
# 1
resp = request.urlopen('http://www.baidu.com') # type:http.client.HTTPResponse
# 2
resp = request.urlopen('http://www.baidu.com')
assert isinstance(resp, http.client.HTTPResponse)
# 3
resp = request.urlopen('http://www.baidu.com')
"""
:type:http.client.HTTPResponse
"""
# 两种方式创建线程
# 第一种,使用继承
class MyThread(Thread):
def run(self):
print("使用继承")
if __name__ == '__main__':
my = MyThread()
my.start()
# 第二种
t = Thread(target=lambda: print("直接使用Thread类"))
t.start()
https://docs.python.org/zh-cn/3.8/library/index.html
https://www.liaoxuefeng.com/wiki/1016959663602400/1017681679479008
数据类型
,它具备tuple的不变性,又可以根据属性来引用
,使用十分方便from collections import namedtuple
if __name__ == '__main__':
Point = namedtuple("Point", ["x", "y"])
p = Point(10,20)
print(p.x)
print(p.y)
print(p)
双向链表
可以快速插入,删除元素key不存在时,返回一个默认值
,就可以用defaultdict # 带默认值的dict
dd = defaultdict(lambda: "None")
print(dd["k"])
有序Dict
按插入顺序排序计数器
:为序列元素计数 c = Counter()
c.update((1, 1, 1, 2, 2))
print(c)
~/.pip/pip.conf
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
[install]
trusted-host=pypi.tuna.tsinghua.edu.cn