使用任意变量作为`exec`的命名空间

时间:2015-02-27 12:46:07

标签: python python-3.x dynamic-code

使用exec使用此测试代码(使用Python 3.4):

vals = {}
exec('def fun(): print("Hello from fun")', vals)
exec('def main(): fun()', vals)
vals['main']()

输出结果为:

  

Hello from fun

但是我没想到这会起作用,因为我假设funmain被解释为单独的代码片段而没有共同的命名空间来解析main到{{fun中的引用1}}。

那么main的执行如何解决对fun的引用?


添加基于对问题的理解。对于printid valsglobals,很明显这两个函数看到相同的全局变量:

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

     

主要身份证(globals()):32271016

     

fun id(globals()):32271016

     

Hello from fun

因此vals用作exec中代码的全局变量,从而提供连接,如@Dunes和其他描述的注释。感谢。

1 个答案:

答案 0 :(得分:3)

通过向vals两个函数提供exec,您已经提供了公共命名空间。 exec的第二个参数是在任何执行的代码中用于全局引用的字典。执行第一个语句时,它会创建fun并将其存储在全局命名空间(vals)中。因此,当main尝试查找fun时,它发现它不是局部变量,因此尝试在其全局变量中查找fun(也是vals) 。由于fun中存在vals,因此查找工作并检索和调用该函数。如果为每个exec提供了自己的dict,那么这将无效。如果你不提供vals那么调用exec的当前全局变量将被用作全局变量(因此这仍然有用)。