exec内部函数声明的Python问题

vcbbcvbcv

为什么我不能在另一个函数中的 exec 中声明一个函数?我真的不知道为什么会这样,有没有办法让它工作。我发现了这个:Invoking problem with defined in exec()但这并不是我想要的,在我的情况下,我不希望 exec 代码是任意的。

def test():
    exec("""
def this():
    print('this')

def main():
    this()

main()
""")

test()

回报:

Traceback (most recent call last):
  File "/t.py", line 12, in <module>
    test()
  File "/t.py", line 2, in test
    exec("""
  File "<string>", line 8, in <module>
  File "<string>", line 6, in main
NameError: name 'this' is not defined

当我在函数之外执行 exec 时,它工作得很好,为什么?

exec("""
def this():
    print('this')

def main():
    this()

main()
""")
宫城先生

TLDR:提供显式的全局字典来执行代码“就好像”它在顶层运行一样。


Python 使用词法作用域,这大致意味着根据源代码中的嵌套查找名称。例如,嵌套函数可以访问外部函数的变量。

def foo():
    bar = 12
    def qux():
        print(bar)  # nested scope accesses outer scope
    return qux

值得注意的是,这种名称查找发生在源代码编译时——编译器知道这两者fooqux访问bar,所以它必须对两者都可用。内层函数直接编译看外层函数的变量。

相反,如果一个函数没有嵌套,它对非局部变量的名称查找会自动进入全局范围。

def qux():
    print(bar)  # top-level scope accesses global scope

当我们在函数中编码时,这是一个问题exec:一个定义如被编译为在全局范围内def main(): this()查找,在函数的当前本地范围内运行。this exec

在所有情况下,如果省略了可选部分,则代码将在当前范围内执行。

因此,全局查找this但在本地定义。1编译器分别解析和 exec 代码,因此它不知道查找意味着被视为嵌套。结果,查找失败。def test

为了exec编码“好像”它在顶层运行,提供一个显式的就足够了globals——例如一个新的命名空间{}或实际的globals().

def test():
    exec("""
def this():
    print('this')

def main():
    this()

main()
""", {})
#    ^^ globals namespace for exec

test()

这意味着代码现在在(它自己的)全局命名空间中运行,这也是函数查找搜索的地方。


1这可以通过打印globals()/locals()和检查功能说明来检查。dis.dis(main)在 exec 中会产生:

  6           0 LOAD_GLOBAL              0 (this)
              2 CALL_FUNCTION            0
              4 POP_TOP
              6 LOAD_CONST               0 (None)
              8 RETURN_VALUE

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章