我正在试验Python,看到下面dis.dis的输出,我感到很惊讶。给出以下两行:
[i for i in range(10)]
print("OK")正如您所看到的,这两条线导致了3个块。为什么第一和第三块属于第一行?这也是按照这个顺序执行的吗?我希望C或C++编译器能给出这样的无序指令,但我不明白第三个部分:
1 0 LOAD_CONST 0 (<code object <listcomp> at 0x109664540, file "example.py", 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 POP_TOP
2 18 LOAD_NAME 1 (print)
20 LOAD_CONST 3 ('OK')
22 CALL_FUNCTION 1
24 POP_TOP
26 LOAD_CONST 4 (None)
28 RETURN_VALUE
Disassembly of <code object <listcomp> at 0x109664540, file "test", line 1>:
1 0 BUILD_LIST 0
2 LOAD_FAST 0 (.0)
>> 4 FOR_ITER 8 (to 14)
6 STORE_FAST 1 (i)
8 LOAD_FAST 1 (i)
10 LIST_APPEND 2
12 JUMP_ABSOLUTE 4
>> 14 RETURN_VALUE>>是干什么用的?文档将它们描述为a labelled instruction, indicated with >>,,但我不能在上面的示例中应用这个注释。
发布于 2019-10-04 05:14:04
<listcomp>是解释器在处理列表理解时创建的一个单独的对象。它用于隔离理解命名空间(循环变量i)并构建列表。它首先被创建,然后经过一些准备之后调用,最后被丢弃。
从一开始,您就可以看到创建了助手:
1 0 LOAD_CONST 0 (<code object <listcomp> at 0x109664540, file "example.py", line 1>)
2 LOAD_CONST 1 ('<listcomp>')
4 MAKE_FUNCTION 0由于CPython是基于堆栈的VM,所以以前的指令可以在堆栈上为以后的指令设置参数。在这里,您可以看到代码对象(反汇编中的第三个块)正在加载,一个名称正在加载,最后一个函数是从刚才添加到堆栈中的内容创建的。请注意,您实际上可以看到这个函数,例如,如果理解中有错误,它就会出现在回溯中。
接下来,Python在范围内创建一个迭代器:
6 LOAD_NAME 0 (range)
8 LOAD_CONST 2 (10)
10 CALL_FUNCTION 1
12 GET_ITER这将加载range函数及其参数,然后应用它--我们现在在堆栈的顶部有了range(10)。最后,删除范围并用它的迭代器替换它。
最后,Python调用助手函数:
14 CALL_FUNCTION 1请记住,我们的堆栈之前填充了助手函数<listcomp>和范围迭代器。其他的东西都从堆里消失了。因此,在这里,Python使用范围迭代器作为参数调用助手函数。助手返回列表理解所产生的列表。
什么是>>的
它们是字节码执行中可能的跳转/分支的可视化。
例如,可以执行for循环(跳转到循环的末尾),也可以有另一个项(跳转到循环的开始)。在您的反汇编中可以看到这一点:
>> 4 FOR_ITER 8 (to 14)
6 STORE_FAST 1 (i)
8 LOAD_FAST 1 (i)
10 LIST_APPEND 2
12 JUMP_ABSOLUTE 4
>> 14 RETURN_VALUE指令4是循环的迭代(即在列表理解中)。它的参数(右边)是块大小,即8。这意味着当完成时,它跳过to 14 --标记为>>的返回指令。由于循环必须对每一项重复,所以它的最后一条指令12是在4处跳转到循环指令--也是用>>标记的。
https://stackoverflow.com/questions/58229923
复制相似问题