2020年2月4日,在武汉肺炎还没解决的日子,我花了一天的时间重新阅读了流畅的Python一书中的重点部分,在此记录下比较常用的知识点.

我关注的主要是Python比较基础的部分,其中对于python继承和多线程部分没有关注,就个人使用而言,要显示的使用继承和多线程还是太少.


为什么len不是普通方法?

实用胜于纯粹, 如果x是一个内置类型的示例,那么使用len(x)的速度会非常快.
原因是: CPython会直接从一个C结构体读取对象的长度,完全不会调用其他的任何方法.因为获取集合的长度是很常见的操作,故此操作必须高效.换句话说,它之所以不是普通方法,是为了方便python自带的数据结构得到长度,对于其他的abs()类似方法也是同理的.

列表推导式&生成器表达式

  1. 列表推导式使用的是 [], 生成器表达式使用的是 ()
  2. 列表推到式是先生成所有的数据,然后供给其他程序使用;生成器表达式是其他程序需要的时候,按需生成,这种方式更节省内存.

    元组

  3. 元组”不可变”体现在元素的引用不可变动.

  4. 元组拆包规则
  5. 具名元组:collections.namedtuple

    +=操作的实现逻辑

    对与对象来说, += 对应的方法是iadd,该方法存在的话,对于可变序列则不会返回一个新的对象.
    如果iadd方法不存在,那么 a += b 便等价于 a = a+b,此时调用的不是iadd方法而是add方法,而add方法又会产生新的对象,所以a的引用就不等于相加前a的引用了

    序列的浅复制

    浅复制我认为便是重新创建一个新的对象,而新的对象和被复制的对象的属性的引用指向是相同的(除了基本数据类型是复制值之外).

  6. 对切片的赋值必须是列表

  7. 切片是浅复制
  8. 列表的构造方法list()也是浅复制

    is和==

    is比较的是两个对象的地址(也就是引用)
    ==调用的是eq方法,对于大部分内置类型来说比较值比比较同一个对象更加有意义,所以是比较的元素值,但是对于自定义或者其他没有复写object类的eq方法便是比较的两个对象的地址

如果让对象可hash,必须注意什么?

  1. eq方法中所有的对象都是可以hash的
  2. eq方法相等的对象其hash值也必须一样

dict和set

  1. 字典和集合都涉及到hash
  2. 字典和集合都维护着一个hash表,所以相对于其他数据结构是比较耗内存的
  3. 关于set查找某个元素是否存在的过程:首先得到该元素的Hash值,到hash表中对比是否存在该hash值,如果存在,然后对比元素的值是否相等,相等则存在.如果不存在该元素的hash值,那么便不存在该元素.

闭包

闭包涉及到自由变量.如果不涉及可变对象,那么便需要在闭包里面的函数中声明nonlocal权限的属性才可使用闭包的权限.
闭包给我的感受便是延伸了一个作用域,该作用域在使用之后被清除但是闭包所在的作用域没有被清除,于是便出现了上一次函数使用之后的值

闭包和装饰器

  1. 闭包是装饰器的基础
  2. 装饰器中除了内部函数之外的逻辑在导入模块的时候便被执行
  3. 装饰器的构建有多个方法,建议使用functools

    上下文管理器

  4. 上下文管理器就是环境管理器,在这部分领域之间可以暂时重新定义一个环境

  5. 重载enter方法和exit便可以定义一个上下文环境
  6. 使用@contextmanager可以省略第二点的一些代码,更快速的定义环境