Python 是否在模块中隐式 return None?
Does Python implicitly return None in modules?
我在 Python 字节码和 dis
模块一起玩时,我注意到一些关于为模块生成的字节码的事情。给定一个名为 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
and RETURN_VALUE
,如果我的理解是正确的,将常量 None
放在 值堆栈 上,因此return它。
隐式执行模块 return None
如果是,为什么?
是的,简而言之,模块隐式执行 return 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;这包括 class 定义:
>>> 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和returns(LOAD_CONST
)值在最上面堆栈到被调用者(如果存在的话)。
唯一需要注意的是,指定自定义 return 值仅允许用于函数,在 class 定义和模块中,return 值没有太多一个目的,因此尝试指定一个目的会导致适当的 SyntaxError
.
对于对此源代码感兴趣的人,您可以通过逐步执行 compile.c
中定义的函数,从 [=19] 中的文档中找到它=]:
* 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.
和4.
或compiler_mod
and assemble
函数
我在 Python 字节码和 dis
模块一起玩时,我注意到一些关于为模块生成的字节码的事情。给定一个名为 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
and RETURN_VALUE
,如果我的理解是正确的,将常量 None
放在 值堆栈 上,因此return它。
隐式执行模块 return None
如果是,为什么?
是的,简而言之,模块隐式执行 return 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;这包括 class 定义:
>>> 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和returns(LOAD_CONST
)值在最上面堆栈到被调用者(如果存在的话)。
唯一需要注意的是,指定自定义 return 值仅允许用于函数,在 class 定义和模块中,return 值没有太多一个目的,因此尝试指定一个目的会导致适当的 SyntaxError
.
对于对此源代码感兴趣的人,您可以通过逐步执行 compile.c
中定义的函数,从 [=19] 中的文档中找到它=]:
* 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.
和4.
或compiler_mod
and assemble
函数