dis
模块使用Python字节码。给定一个名为mod.py
的小测试模块:
if __name__ == "__main__":
print("Hello World")
我使用compile()
函数为它创建了一个代码对象:
>>> cobj = compile(open("mod.py").read(), "mod", "exec")
然后,反汇编代码对象以查看字节码:
>>> dis.dis(cobj)
1 0 LOAD_NAME 0 (__name__)
3 LOAD_CONST 0 ('__main__')
6 COMPARE_OP 2 (==)
9 POP_JUMP_IF_FALSE 22
2 12 LOAD_NAME 1 (print)
15 LOAD_CONST 1 ('Hello World')
18 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
21 POP_TOP
>> 22 LOAD_CONST 2 (None)
25 RETURN_VALUE
令我印象深刻的是最后两个命令LOAD_CONST
和RETURN_VALUE
,如果我的理解正确,请将常量None
放在值堆栈上因此归还。
模块是否隐式返回None
,如果是,为什么?
答案 0 :(得分:6)
是的,简而言之,模块会隐式返回None
,以便 ceval.c
内的大评估循环能够检测到当前帧的完成时间和终止。
有趣的是,即使从终端解释了一个完全为空的python文件,你也可以看到这一点:
jim@lpt> touch file.py
jim@lpt> python -m dis file.py
1 0 LOAD_CONST 0 (None)
3 RETURN_VALUE
此行为不仅限于模块,而是 for anything that can form a code block ;这包括类定义:
>>> from dis import dis
>>> co = compile("class mycls: pass", filename = "stdin", mode = "exec")
>>> dis(co.co_consts[0]) # co_consts[0] contains class definition
1 0 LOAD_NAME 0 (__name__)
3 STORE_NAME 1 (__module__)
6 LOAD_CONST 0 ('mycls')
9 STORE_NAME 2 (__qualname__)
12 LOAD_CONST 1 (None)
15 RETURN_VALUE
和功能正文:
>>> def foo(): pass
>>> dis(foo)
1 0 LOAD_CONST 0 (None)
3 RETURN_VALUE
即RETURN_VALUE
字节码命令 terminates the current block that was executing 并将堆栈顶部的值返回(LOAD_CONST
)给被调用者(如果存在)一个)。
唯一需要注意的是,指定自定义返回值仅允许用于函数,在类定义和模块中,返回值没有太多用途,因此尝试在适当的{中指定一个结果{ {1}}。
对于对此源代码感兴趣的人,您可以通过SyntaxError
中的文档逐步执行 compile.c
中定义的函数来找到它:
compile.c
相关步骤为 * The primary entry point is PyAST_Compile(), which returns a
* PyCodeObject. The compiler makes several passes to build the code
* object:
* 1. Checks for future statements. See future.c
* 2. Builds a symbol table. See symtable.c.
* 3. Generate code for basic blocks. See compiler_mod() in this file.
* 4. Assemble the basic blocks into final code. See assemble() in
* this file.
* 5. Optimize the byte code (peephole optimizations). See peephole.c
和3.
或 compiler_mod
和 assemble
功能