Python Reading Notes

Python

  • 1.Python支持一种名为容器的数据结构。两种主要的容器是序列(如列表和元组)和映射(如字典),集合既不是序列也不是映射。
    (《Python基础教程第三版》 Chapter 2.1)

  • 2.Python 3 提供了一种句法,用于为函数声明中的参数和返回值附加元数据。函数声明中的各个参数可以在:之后增加注解表达式。如果参数有默认值,注解放在参数名和=号之间。如果想注解返回值,在)和函数声明末尾的:之间添加->和一个表达式。那个表达式可以是任何类型。注解中最常用的类型是类(如 strint)和字符串(如 int > 0)。注解不会做任何处理,Python对注解所做的唯一的事情是,把它们存储在函数的__annotations__属性里。仅此而已,Python不做检查、不做强制、不做验证,什么操作都不做。换句话说,注解对Python解释器没有任何意义。注解只是元数据,可以供IDE、框架和装饰器等工具使用。写作本书时,标准库中还没有什么会用到这些元数据,唯有inspect.signature()函数知道怎么提取注解。

1
2
3
4
5
6
>>> def clip(text:str, max_len:'int > 0'=80) -> str:
>>> pass

>>> from clip_annot import clip
>>> clip.__annotations__
{'text': <class 'str'>, 'max_len': 'int > 0', 'return': <class 'str'>}
  • 3.pprint 是个卓越的打印函数,能够更妥善地打印输出。。
    (《Python基础教程第三版》 Chapter 10.1.3)

  • 4.打开文件或程序

1
2
3
os.system(r'C:\"Program Files (x86)"\"Mozilla Firefox"\firefox.exe')
os.startfile(r'C:\Program Files (x86)\Mozilla Firefox\firefox.exe')
(《Python基础教程第三版》 Chapter 10.3.2
  • 5.random模块包含生成伪随机数的函数,背后是可预测的。要求真正的随机(加密或实现与安全相关功能),考虑使用os模块的urandom()函数。模块random中的SystemRandom类的功能与urandom类似,可提供接近于真正随机的数据。
    (《Python基础教程第三版》 Chapter 10.3.6)

  • 6.容器序列(listtuplecollections.deque)存放的是它们所包含的任意类型的对象的引用,这些序列能存放不同类型的数据。
    扁平序列(strbytesbytearraymemoryviewarray.array)存放的是值而不是引用,只能容纳一种类型。
    可变序列(listbytearrayarray.arraycollections.dequememoryview
    不可变序列(tuplestrbytes)。
    (《流畅的Python》 Chapter 2.1)

  • 7.用 “*”来忽略可迭代对象(元组)拆包时不需要的多余元素,或用占位符“_”来取代无用的单个元素。
    (《流畅的Python》 Chapter 2.3.1)

  • 8.在Python 3之前,元组可以作为形参放在函数声明中,例如def fn(a, (b, c), d):。然而 Python 3不再支持这种格式。需要弄清楚的是,这个改变对函数调用者并没有影响,它改变的是某些函数的声明方式。
    (《流畅的Python》 Chapter 2.3.3)

  • 9.对不可变序列进行重复拼接操作的话,效率会很低,因为每次都有一个新对象,而解释器需要把原来对象中的元素先复制到新的对象里,然后再追加新的元素。str 是一个例外,因为对字符串做 += 实在是太普遍了,所以 CPython 对它做了优化。为str初始化内存的时候,程序会为它留出额外的可扩展空间,因此进行增量操作的时候,并不会涉及复制原有字符串到新位置这类操作。
    (《流畅的Python》 Chapter 2.6)

  • 10.一个关于+=的谜题

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> t = (1, 2, [30, 40])
>>> t[2] += [50, 60]

到底会发生下面 4 种情况中的哪一种?
a. t 变成 (1, 2, [30, 40, 50, 60])。
b. 因为 tuple 不支持对它的元素赋值,所以会抛出 TypeError 异常。
c. 以上两个都不是。
d. a 和 b 都是对的。

答案是d

有读者提出,如果写成 t[2].extend([50, 60]) 就能避免这个异常。确实是这样,但这个
例子是为了展示这种奇怪的现象而专门写的。

(《流畅的Python》 Chapter 2.6)

  • 11.反汇编函数dis
1
2
3
4
5
6
7
8
9
10
11
12
>>> from dis import dis
>>> dis('s[a] += b')
1 0 LOAD_NAME 0 (s)
2 LOAD_NAME 1 (a)
4 DUP_TOP_TWO
6 BINARY_SUBSCR
8 LOAD_NAME 2 (b)
10 INPLACE_ADD
12 ROT_THREE
14 STORE_SUBSCR
16 LOAD_CONST 0 (None)
18 RETURN_VALUE
  • 12.一个小试验告诉我,用 array.fromfile 从一个二进制文件里读出 1000 万个双精度浮点数只需要 0.1 秒,这比从文本文件里读取的速度要快 60倍,因为后者会使用内置的 float 方法把每一行文字转换成浮点数。另外,使用 array.tofile 写入到二进制文件,比以每行一个浮点数的方式把所有数字写入到文本文件要快 7 倍。另外,1000 万个这样的数在二进制文件里只占用 80 000 000 个字节(每个浮点数占用 8 个字节,不需要任何额外空间),如果是文本文件的话,我们需要 181 515 739个字节。
    (《流畅的Python》 Chapter 2.9.1)

  • 13.直到我写这本书的时候,Python 词汇表[https://docs.python.org/3/glossary.html#term-hashable] 里还在说“Python 所有的不可变类型都是可散列的”。这个说法其实是不准确的,比如虽然元组本身是不可变序列,它里面的元素可能是其他可变类型的引用
    (《流畅的Python》 Chapter 3.1)

  • 14.从 Python 3.3 开始,str、bytes 和 datetime 对象的散列值计算过程中多了随机的“加盐”这一步。所加盐值是 Python进程内的一个常量,但是每次启动 Python 解释器都会生成一个不同的盐值。随机盐值的加入是为了防止 DOS 攻击而采取的一种安全措施。
    (《流畅的Python》 Chapter 3.9.2)

  • 15.dict的实现及其导致的结果
    (《流畅的Python》 Chapter 3.9.3)

未完待续…