1
dict()is slower than{}list()is slower than()
- 需要符号查找(不能预先知道
list()有没有被重定义) - 方法调用
- 要检查有没有可迭代变量传入
2
特殊方法
__len__()__getitem__()__setitem__()__iter__()
是为了被python解释器调用的,自己不用调用它们,所以没有A.__len__()方法,只有len(A)
3
自定义布尔值 -> 实现__bool__
4
__str__(): readable, 面向用户__repr__(): unambigous, 面向DEV
5
The Zen of Python
-
- 实用胜于纯粹
-
- 不能让特例特殊到开始破坏规则
6
内置序列类型
- 容器序列:任意类型,引用 -
list, tuple, deque- 扁平序列:单一类型,值 -
str(3.0), byte(3.0), bytearray, memoryview
- 可变序列(MutableSequence):
list, deque…- 不可变序列(Sequence):
tuple, str, byte
7
- list comprehension = listcomps 列表推导
- generator expression = genexps 生成器表达式
8
chr(65)-> Aord(A)-> 65unichr(12345)-> u'\u3039'
9
列表推导的作用只有一个: 生成列表
10
genexps优于listcomps
genexps遵守了迭代器协议,可以逐个产生元素,而不是先建立一个完整的列表,避免了额外的内存占用
11
元组拆包
a,b = (a,b)a,b = b,a两个变量值交换
12
*来处理剩下的元素
Python3: 平行赋值: a,b,*rest = range(5) -> (0,1,[2,3,4])
13
namedtuple和tuple创建实例消耗内存一样,因为字段名都存在类里:
_fileds类属性_make(iterable)类方法_asdict()实例方法
14
tuple没有__reversed__方法,但可以reversed(my_tuple)
15
切片赋值:改变list中连续多个值
l = list(range(10))
l[2:5] = [20,30]
-> l:[0,1,20,30,5,6,7,8,9]
16
__iadd__方法:就地加法
+=__iadd__*=__imul__
17
id(object) -> return “Identity(内存地址)” of an object
+=or*=用在list上,不改变id+=or*=用在tuple上,改变id,重新创建一个obj
18
如果一个方法对对象进行的是就地改动,那就应该返回None
19
list.sort-> 就地改sorted()-> 新建一个列表返回
Example:
sorted(fruits, key=len)
sorted(fruits, key=lower) …
20
bisect 二分查找
bisect(haystack, needle)
insort(seq, item)-> 插入后仍保持升序
21
字符串格式化
' '.format(a,b,c)
{0}-> 位置参数{name}-> 关键字参数{0[0]}-> 对list使用索引{0:*(填充字符)>(右对齐)10(宽度)}-> 填充与格式化
22
array 场景->1000万个浮点数
deque 场景->需要频繁对序列进行FIFO
23
memoryview
24
numpy, scipy
25
collections.deque:线程安全、快速从两端添加、删除元素。
场景:存放最近使用的几个元素
rotate(3):右边三个到左边。rotate(-4):左边四个到右边。
appendleft():单个。extend, extendleft: 队列。
26
- **
散列表**是字典类型性能出众的根本原因。 collections.abc.Mapping的instance- 原子不可变数据类型(
str, byte和数值类型) - 散列值就是
id()函数的返回值
27
字典创建方法
a = dict(one=1,two=2,three=3)
b = {'one':1,'two':2,'three':3}
c = dict(zip(['one','two','three'],[1,2,3]))
- 字典推导
dictcomp
28
**dict.setdefault**处理不存在于dict中的key
29
**collections.defaultdict**是处理找不到key的一个选择
dd = defautdict(list),如果'new-key'不存在,dd['new-key']会执行:
list()建新列表
- 这个新列表作为
值,new-key为key,放入dd
- 返回这个列表的引用
30
__missing__只会被__getitem__调用
31
如果要自定义一个映射类型,应该继承collections.UserDict
32
字典的变种
collections.OrderedDict:popitem方法 -> 删除并返回
collections.ChainMap: 多个字典逐个查找
collections.Counter:
ct = Counter('abracadabra')
- ->
Counter({'a':5,'b':2,'r':2,'c':1,'d':1})
UserDict用户涌来继承写子类
TransformDict
33
不可变映射类型
types.MappingProxyType:只读的映射视图
34
set -> 许多唯一对象的聚集;frozenset -> 不可变
集合
- 用于去重复:
list->set->list
- 合集,交集,差集 -> 场景:元素出现次数
如果是空集必须写成set()
35
散列表:稀疏数组(总有空白元素的数组)
key:value -> 一个表元
因为所有表元大小一致,所以可以通过偏移量来读取某个表元
用hash()来计算散列值
36
存放数量巨大的记录用tuple或namedtuple
dict 散列 -> 内存消耗大
37
dict:空间换时间 -> 读取快 但 内存消耗大
Python解释器可能为字典扩容 -> 导致新建一个更大的散列表
38
集合 set
- 元素必须可散列
- 很耗内存
- 高效查找
- 次序取决于添加次序
- 添加元素可能改变已有元素次序(37中的扩容)
39
字符的最佳定义是Unicode字符
Python3 从 str对象中获取的元素是Unicode字符
字符的具体表述取决于所用的编码
- 编码:码位 -> 字节序列
- 解码:字节序列 -> 码位(字符的标识)
40
字面量:双眼所见
41
utf_8 的别名:utf8, u8, utf-8
42
编码种类
latin1(iso8859-1):是其他编码的基础cp1252:Windows制定的latin1的超集,添加了有用的符号gb2312:用于编码简体中文的陈旧标准utf-8:web最常见的8位编码,与ASCII兼容
43
Python3 中默认使用 utf8 编码源码
44
判断编码
以下是肉眼方法
HTTP和XML,包含明确指明内容编码的首部
- 包含大于127的字节值,那么就不是ASCII
- 如果
b'\x00'经常出现,那么就不是8位编码方案
统一字符编码侦测包:Chardet
45
Python中,函数是一等对象
- 运行时创建
- 能赋值给变量或数据结构中的元素
- 能作为参数传给函数
- 能被
return
46
__doc__用于生成对象的帮助文本
47
函数式编程:特点之一是使用高阶函数
高阶函数:
- 接受函数作为参数
- 或
- 把函数作为结果返回
48
map, filter 和 reduce 在Python3中已经不是内置函数
被 listcomps 和 genexps 所替代(可读性原因)
49
匿名函数:lambda
50
使用callable()函数来判断一个对象能否调用
51
用户定义可调用类型,只需实现实例方法__call__
52
函数内省
53
函数有但一般对象没有的特殊方法:
__annotations____call__:实现()运算符
54
函数注解只存放在__annotations__属性里,Python不做检查、验证、强制…
注解只是元数据,可以供IDE、框架和装饰器工具使用
55
函数式编程
operator->itemgetter(get下标),attrgetter(get name)
functools内包含reduce函数,partial冻结参数,partialmethod
Example:
triple = partial(mul,3)
triple(7) -> 21
56
globals() 策略模式
57
命令模式:是回调机制的面向对象替代品
58
nonlocal关键字。
装饰器 目的是增强函数
59
元编程 -> 在运行时改变程序的行为
装饰器的两大特性:
- 能把装饰的函数替换成其他函数
- 在加载模块时立即执行
60
装饰器 在被装饰的函数定义之后立即运行。通常是在导入时(加载模块时)
61
变量作用域规则
b = 6
def f2(a):
print(a)
print(b)
b = 9
f2(3)
输出 3, local variable 'b' referenced before assignment
Python编译函数定义体时,它判断b是局部变量,因为在函数中给它赋值了。生成的字节码证实了这种判断,Python会尝试从本地环境获取b。后面调用f2(3)时,f2的定义体会获取并打印局部变量a的值,但是尝试获取局部变量b的值时,发现b没有绑定值。
这不是缺陷,而是设计选择:Python不要求声明变量,但是假定在函数定义体中赋值的变量是局部变量。
如果在函数中赋值时想让解释器把b当成全局变量,要使用global声明。
62
闭包 不等同于 匿名函数
闭包是延伸了作用域的函数,函数是不是匿名的没有关系,关键是它能否访问定义体之外定义的非全局变量