Python是否在模块中隐式返回None?

时间:2016-06-19 18:10:23

标签: python python-2.7 python-3.x module bytecode

当我注意到为模块生成的字节码时,我正在使用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_CONSTRETURN_VALUE,如果我的理解正确,请将常量None放在值堆栈上因此归还。

模块是否隐式返回None,如果是,为什么?

1 个答案:

答案 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 功能