1. Python的特殊方法

1.1 __getitem____setitem__:通过[]取值时会调用;通过此函数,自定义对象即变成可迭代;

1.2 __len__:对应len()方法的调用;

1.3 __contain__:对应in运算符;如果未实现,则in运算符会按顺序做一次迭代搜索;

1.4 __init__:比较常用的一个特殊方法,子类可实现该方法调用超类的构造器;

1.5 __repr__:将对象以字符串形式表达,对应通过repr函数获取(调试或交互控制台用到);

1.6 __str__:str函数或print函数调用;不存在时解释器会尝试调用__repr_;

2. 列表、元组

2.1 列表推导

symbols = 'abcd'
l = []
l = [c for c in symbols]
# l: [a b c d]

2.2 生成器表达式

生成器表达式和列表推导相比,形式上只是将方括号换为圆括号。
但区别在于:前者逐个产出元素,后者一次生成整个列表。

symbols = 'abcd'
for c in (c for c in symbols):
    print(c)

2.3 元组

tu = (1,2,3)
symbols = 'abcd'
ts = tuple(c for c in symbols)
# ts: ('a', 'b', 'c', 'd')

2.4 元组拆包

t = (1,2,3,4)
a, b, c, d = t
t1, *t2, t3 = t # 平行赋值. t2:[2,3]

1.函数可以通过元组,返回多个参数;
2.不使用中间变量交换两个参数

a,b = b,a

3.通过*将可迭代对象拆开为函数参数:

t = (2,3)
def func(a, b):
    ...
func(*t) # 将t拆为两个参数

2.5 具名元组

from collections import nametuple
City = nametuple('City', 'name country population coordinates')

collections.nametuple需要两个参数,类名 + 各字段名字(多个字符串组成的可迭代对象 \ 空格分隔的字段名组成的字符串)

2.6 切片

[a:b:c]表示在 [a,b) 范围间按照间隔c取元素(c可为负值,表示反向取值)
另外, Numpy中, ...作为多维数组切片的快捷方式。 比如x为四维数组,x[i, ...] 就等于 x[i, :, :, :]

2.7 + * += *=

+ *: 不修改原有对象,会新建对象;
+= *=:对象实现__iadd__\__imul__,则调用;没有则退回 a=a+b 模式。一般可变序列都实现特殊方法,因此是就地操作;

:一个小bug

w1 = [[0]*3 for i in range(3)] # [[0,0,0], [0,0,0], [0,0,0]]
w2 = [[0]*3] *3 # [[0,0,0], [0,0,0], [0,0,0]]
w1[1,2] = 1 # [[0,0,0], [0,0,1], [0,0,0]]
w2[1,2] = 1 # [[0,0,1], [0,0,1], [0,0,1]]

2.8 其他

bisect:通过二分维护有序数组, bisect.bisect, bisect.insort
array.array:数组
memoryview:内存视图
Numpy、Scipy
collections.deque\queue(控制活跃线程数量)\multiprocessing(进程间通信)\asyncio\heapq
... ...

3 字典、集合

3.1 可散列对象

对可散列对象来说:其生命周期内散列值不可变。支持__hash____eq__函数。并且保证a=bhash(a)=hash(b)

元组:只有当所有元素为可散列,元组才为可散列
列表为不可散列

3.2 setdefault处理找不到key

index = {}
index[1].append(1) #Error
index.setdefault(1, []).append(1)

3.3 查询时找不到key的办法

1.通过collections.defaultdict声明dict

work = collections.defaultdict(list) # 不存在时默认用list

2.特殊方法__missing__
该方法只会被__getitem__在获取不到元素时调用

3.4 其他字典变种

collections.OrderDict # 保证插入顺序
collections.ChainMap # key为多个不同映射对象,链式查找key
collections.Counter # 给每个键一个计数器,统计出现次数
collections.UserDict # 让用户继承的dict类
types.MappingProxyType # 可以提供动态dict只读视图

3.5 集合

s = set()
s = {1,2,3}
s1 & s2 # 交集
s1 - s2 # 差集
s1 | s2 # 并集
s1 < s2 # s1是s2真子集
s1 <= s2
s1 > s2 # s1是s2真父集
s1 >= s2

3.6 由可散列引入的注意事项

1.支持__hash____eq__, 若a==b,则hash(a)==hash(b);
2.对自定义对象,默认可散列(散列值由id()获取)。但是,如果对象实现__eq__,则应提供__hash__,否则对象不可散列。
且此时需保证第1点。否则在使用字典、集合时,造成难查bug。
3.键的次序和插入顺序相关:因为可能有的散列冲突,导致新建会被重新换位置;
4.往字典加新键可能改变已有键的顺序:引起了扩容,并由第3点导致顺序改变;
故不能在迭代字典所有键的过程同时,对字典进行修改。