使用exec
(使用Python 3.4)进行此测试代码:
vals = {}
exec('def fun(): print("Hello from fun")', vals)
exec('def main(): fun()', vals)
vals['main']()
输出为:
你好,来自有趣的
但我没想到这会起作用,因为我假设fun
和main
被解释为单独的代码段,而没有公共命名空间来解析main
到fun
中的引用。
那么main
的执行如何解决对fun
的引用呢?
基于加法的理解问题。对于vals
和globals
,使用id
的print
,可以清楚地看出,这两个函数看到相同的全局:
vals = {}
print('id(vals):', id(vals))
exec('def fun(): print("fun id(globals()):", id(globals())); print("Hello from fun")', vals)
exec('def main(): print("main id(globals()):", id(globals())); fun()', vals)
vals['main']()
哪个给出:
id(vals):32271016
主id(globals()):32271016
fun id(globals()):32271016
你好,来自有趣的
因此,vals
被用作exec
中代码的全局变量,从而给出连接,如@Dunes和其他注释所述。谢谢
通过向两个exec
函数提供vals
,您提供了通用名称空间。exec
的第二个参数是一个字典,用于执行的任何代码中的全局引用。当执行第一条语句时,它创建fun
并将其存储在全局名称空间(vals
)中。因此,当main
尝试查找fun
时,它发现它不是局部变量,因此尝试在其全局(也是vals
)中查找fun
。由于fun
存在于vals
中,因此查找工作正常,并且检索和调用函数。如果给每个exec
它自己的dict
,那么这将不起作用。如果不提供vals
,那么调用exec
的当前全局变量将用作全局变量(因此这仍然有效)。