考虑此示例
>>> dis.dis("[1 for i in range(3)]")
1 0 LOAD_CONST 0 (<code object <listcomp> at 0x10d6045d0, file "<dis>", line 1>)
2 LOAD_CONST 1 ('<listcomp>')
4 MAKE_FUNCTION 0
6 LOAD_NAME 0 (range)
8 LOAD_CONST 2 (3)
10 CALL_FUNCTION 1
12 GET_ITER
14 CALL_FUNCTION 1
16 RETURN_VALUE
Disassembly of <code object <listcomp> at 0x10d6045d0, file "<dis>", line 1>:
1 0 BUILD_LIST 0
2 LOAD_FAST 0 (.0) <------ Look at this 🧐🧐
>> 4 FOR_ITER 8 (to 14)
6 STORE_FAST 1 (i)
8 LOAD_CONST 0 (1)
10 LIST_APPEND 2
12 JUMP_ABSOLUTE 4
>> 14 RETURN_VALUE
反汇编的字节码中有一个奇怪的.0
。
通过分析每条指令,我知道它代表一个迭代器iter(range(3))
,但是Python为什么不使用像iter(range(3))
这样的更直观的表示,因为它已经知道了它的值?
这是一个变量名。列表推导的生成函数采用单个参数,该参数使用通常禁止的名称.0
,以确保该名称不与任何常规变量冲突。如果Python必须生成更多名称,它们将使用.1
,.2
等
dis
输出显示.0
,因为LOAD_FAST
指令是从.0
变量中读取的。 dis
不会去寻找变量值来自的表达式;这将是很多额外的工作,通常是不可能的,并且对于它正在分解的字节码也不太适用。