在
python3.13
中,当我尝试拆解[i for i in range(10)]
时,结果如下:
>>> import dis
>>>
>>> dis.dis('[i for i in range(10)]')
0 RESUME 0
1 LOAD_NAME 0 (range)
PUSH_NULL
LOAD_CONST 0 (10)
CALL 1
GET_ITER
LOAD_FAST_AND_CLEAR 0 (i)
SWAP 2
L1: BUILD_LIST 0
SWAP 2
L2: FOR_ITER 4 (to L3)
STORE_FAST_LOAD_FAST 0 (i, i)
LIST_APPEND 2
JUMP_BACKWARD 6 (to L2)
L3: END_FOR
L4: SWAP 2
STORE_FAST 0 (i)
RETURN_VALUE
-- L5: SWAP 2
POP_TOP
1 SWAP 2
STORE_FAST 0 (i)
RERAISE 0
ExceptionTable:
L1 to L4 -> L5 [2]
在输出的最后,有一些东西
ExceptionTable
。以前版本的python中不存在。
Python 3.10.0b1 (default, May 4 2021, 00:00:00) [GCC 10.2.1 20201125 (Red Hat 10.2.1-9)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import dis
>>>
>>> dis.dis('[i for i in range(10)]')
1 0 LOAD_CONST 0 (<code object <listcomp> at 0x7f3d412503a0, file "<dis>", line 1>)
2 LOAD_CONST 1 ('<listcomp>')
4 MAKE_FUNCTION 0
6 LOAD_NAME 0 (range)
8 LOAD_CONST 2 (10)
10 CALL_FUNCTION 1
12 GET_ITER
14 CALL_FUNCTION 1
16 RETURN_VALUE
Disassembly of <code object <listcomp> at 0x7f3d412503a0, file "<dis>", line 1>:
1 0 BUILD_LIST 0
2 LOAD_FAST 0 (.0)
>> 4 FOR_ITER 4 (to 14)
6 STORE_FAST 1 (i)
8 LOAD_FAST 1 (i)
10 LIST_APPEND 2
12 JUMP_ABSOLUTE 2 (to 4)
>> 14 RETURN_VALUE
我不明白这意味着什么,也找不到这方面的任何文档。
ExceptionTable
确定引发异常时跳转到哪里,并在 python-3.11 中实现。之前的版本使用单独的操作码来处理这个问题。
python-3.11使用所谓的“零成本”异常处理。 在 python-3.11 之前,异常是由运行时的“块”堆栈处理的。 在零成本异常处理中,支持异常的成本为 最小化。在一般情况下(没有例外)成本 减少到零(或接近于零)。筹集资金的成本 例外情况有所增加,但幅度不大。
以下代码:
def f(): try: g(0) except: return "fail" compiles as follows in 3.10: 2 0 SETUP_FINALLY 7 (to 16) 3 2 LOAD_GLOBAL 0 (g) 4 LOAD_CONST 1 (0) 6 CALL_NO_KW 1 8 POP_TOP 10 POP_BLOCK 12 LOAD_CONST 0 (None) 14 RETURN_VALUE 4 >> 16 POP_TOP 18 POP_TOP 20 POP_TOP 5 22 POP_EXCEPT 24 LOAD_CONST 3 ('fail') 26 RETURN_VALUE
注意从“块”堆栈中压入和弹出的显式指令:SETUP_FINALLY
和
。在 3.11 中,POP_BLOCK
SETUP_FINALLY
和
被删除,替换为POP_BLOCK
用于确定引发异常时跳转到何处的表。1 0 RESUME 0 2 2 NOP 3 4 LOAD_GLOBAL 1 (g + NULL) 16 LOAD_CONST 1 (0) 18 PRECALL 1 22 CALL 1 32 POP_TOP 34 LOAD_CONST 0 (None) 36 RETURN_VALUE >> 38 PUSH_EXC_INFO 4 40 POP_TOP 5 42 POP_EXCEPT 44 LOAD_CONST 2 ('fail') 46 RETURN_VALUE >> 48 COPY 3 50 POP_EXCEPT 52 RERAISE 1 ExceptionTable: 4 to 32 -> 38 [0] 38 to 40 -> 48 [1] lasti
(注意此代码来自python-3.11,以后的版本可能略有 不同的字节码。) 如果指令引发异常,则使用其偏移量来查找 要跳转到的目标。例如,偏移量 22 处的
CALL
属于 范围 4 到 32。因此,如果
引发异常,则控制跳转 偏移 38。g()