Python 3.11 你应该试试的超酷特性
Python 3.11在10月24日发布。它是Python最新版本,运行速度更快且更佳友好。在经过17个月的研发,终于到了可以使用的黄金时期。
和每个发布版本一样,Python 3.11做了大量的变更及提高。你可以通过查看文档来了解大部分内容。这里,我们会阐述最酷且最有影响力的新特性。
教程里将涵盖如下内容:
- 更好的错误信息来帮助代码追踪
- Faster CPython项目加速代码执行
- 在异步代码中使用Task和exception groups
- Python静态类型新增的几个类型特性
- 原生支持TOML格式配置文件
如果你想运行本教程所提供的示例文件,你需要先安装Python 3.11.
零开销异常
Python 3.11内部异常机制有一些不同。异常对象更加轻量,异常处理在except子句不触发时,对try...except语句块优化减少开销,
zero-cost exceptions灵感来自C++和Java语言。旨在在快乐路径时(即无异常发生)几乎没有任何其它多余的开销,发生异常的情况仍需要开销处理。
zero-cost exception通过编译器构建字节码时创建一个jump table。这些表在异常发生时使用。如果没发生异常的话,try语句没有任何运行时开销。
我们再来看看早期的倒数例子。我们添加了一些异常处理:
>>> def inverse(number):
... try:
... return 1 / number
... except ZeroDivisionError:
... print("0 has no inverse")
如果我们计算0的倒数时,ZeroDivisionError会抛出。这里我们使用异常补货然后打印了描述信息。我们可以使用dis来看看底层的字节码:
>>> import dis
>>> dis.dis(inverse)
1 0 RESUME 0
2 2 NOP
3 4 LOAD_CONST 1 (1)
6 LOAD_FAST 0 (number)
8 BINARY_OP 11 (/)
12 RETURN_VALUE
>> 14 PUSH_EXC_INFO
4 16 LOAD_GLOBAL 0 (ZeroDivisionError)
28 CHECK_EXC_MATCH
30 POP_JUMP_FORWARD_IF_FALSE 19 (to 70)
32 POP_TOP
5 34 LOAD_GLOBAL 3 (NULL + print)
46 LOAD_CONST 2 ('0 has no inverse')
48 PRECALL 1
52 CALL 1
62 POP_TOP
64 POP_EXCEPT
66 LOAD_CONST 0 (None)
68 RETURN_VALUE
4 >> 70 RERAISE 0
>> 72 COPY 3
74 POP_EXCEPT
76 RERAISE 1
ExceptionTable:
4 to 10 -> 14 [0]
14 to 62 -> 72 [1] lasti
70 to 70 -> 72 [1] lasti
咱也不需要去过多关心字节码意义。但是我们可以简单观察出最左边其实就会对应代码行。行2就是try,转换为了NOP指令,该指令啥也不干。底部那东西就是我们提到的exception table。该jump table就是用来专门处理异常的。
Python 3.10及早期,云行时异常处理有一些开销。例如,try语句编译成SETUP_FINALLY指令,它包含了一个指向第一个exception块的指针。通过引入jump table无异常发生时得到速度提升。
Zero-cost exceptions非常适合Easier to ask forgiveness than permission编码风格代码,它风格会大量使用try...except语句。