2020年2月4日,在武汉肺炎还没解决的日子,我花了一天的时间重新阅读了流畅的Python一书中的重点部分,在此记录下比较常用的知识点.
我关注的主要是Python比较基础的部分,其中对于python继承和多线程部分没有关注,就个人使用而言,要显示的使用继承和多线程还是太少.
为什么len不是普通方法?
实用胜于纯粹, 如果x是一个内置类型的示例,那么使用len(x)的速度会非常快.
原因是: CPython会直接从一个C结构体读取对象的长度,完全不会调用其他的任何方法.因为获取集合的长度是很常见的操作,故此操作必须高效.换句话说,它之所以不是普通方法,是为了方便python自带的数据结构得到长度,对于其他的abs()类似方法也是同理的.
列表推导式&生成器表达式
- 列表推导式使用的是 [], 生成器表达式使用的是 ()
列表推到式是先生成所有的数据,然后供给其他程序使用;生成器表达式是其他程序需要的时候,按需生成,这种方式更节省内存.
元组
元组”不可变”体现在元素的引用不可变动.
- 元组拆包规则
-
+=操作的实现逻辑
对与对象来说, += 对应的方法是iadd,该方法存在的话,对于可变序列则不会返回一个新的对象.
如果iadd方法不存在,那么 a += b 便等价于 a = a+b,此时调用的不是iadd方法而是add方法,而add方法又会产生新的对象,所以a的引用就不等于相加前a的引用了序列的浅复制
浅复制我认为便是重新创建一个新的对象,而新的对象和被复制的对象的属性的引用指向是相同的(除了基本数据类型是复制值之外).
对切片的赋值必须是列表
- 切片是浅复制
- 列表的构造方法list()也是浅复制
is和==
is比较的是两个对象的地址(也就是引用)
==调用的是eq方法,对于大部分内置类型来说比较值比比较同一个对象更加有意义,所以是比较的元素值,但是对于自定义或者其他没有复写object类的eq方法便是比较的两个对象的地址
如果让对象可hash,必须注意什么?
- eq方法中所有的对象都是可以hash的
- eq方法相等的对象其hash值也必须一样
dict和set
- 字典和集合都涉及到hash
- 字典和集合都维护着一个hash表,所以相对于其他数据结构是比较耗内存的
- 关于set查找某个元素是否存在的过程:首先得到该元素的Hash值,到hash表中对比是否存在该hash值,如果存在,然后对比元素的值是否相等,相等则存在.如果不存在该元素的hash值,那么便不存在该元素.
闭包
闭包涉及到自由变量.如果不涉及可变对象,那么便需要在闭包里面的函数中声明nonlocal权限的属性才可使用闭包的权限.
闭包给我的感受便是延伸了一个作用域,该作用域在使用之后被清除但是闭包所在的作用域没有被清除,于是便出现了上一次函数使用之后的值