为什么exec()在函数内部调用时的工作方式不同,以及如何避免它

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (10)

我试图在python中的exec语句中声明两个函数。我们称它们为f1()f2()

我发现当在某个函数内部调用exec时,f2()没有f1()的可见性。但是,当exec和函数调用放在全局代码中时,不会发生这种情况。

# Case 1: Working fine

code = """
def f1(): print "bar"
def f2(): f1()
"""

exec(code)
f2() # Prints "bar" as expected
# Case 2: Throws NameError: global name 'f1' is not defined

code = """
def f1(): print "bar"
def f2(): f1()
"""

def foo():
    exec(code)
    f2() # NameError

foo()

有人可以解释我如何避免NameError并使exec在函数内部工作吗?

提问于
用户回答回答于

使用exec是危险的,几乎总是有更好的方法。

但是,在第一种情况下回答你的问题时,f1()和f2()都在全局命名空间中,因此当你调用f2()时它可以找到f1()。在第二种情况下,它们是在foo()函数的本地空间中创建的。当调用f2()时,它找不到本地f1()定义。

您可以使用以下方法修复此

code = """
global f1
def f1(): print "bar"
def f2(): f1()
"""
def foo():
    exec(code)
    f2()
foo()

再次 - 这几乎肯定不是你想要解决这个问题的方式。

**编辑**发布了我一直在检查的错误版本的代码,这个版本是我原本要包含的内容。

用户回答回答于

exec()接受第二个参数globals。正如文档中所解释的那样:

注意内置函数globals()和locals()分别返回当前的全局和本地字典,这可能有助于传递用作exec()的第二个和第三个参数。

所以你可以通过在globals()中显式传入来完成这项工作:

code = """
def f1(): print ("bar")
def f2(): f1()
"""

def foo():
    exec(code, globals())
    f2() # works in python2.7 and python3

foo()

如果要精确控制范围,可以将对象传递到exec

code = """
def f1(): print ("bar")
def f2(): f1()
"""

def foo():
    context = {}
    exec(code, context)
    context['f2']() 

foo() 

扫码关注云+社区

领取腾讯云代金券