我正在尝试在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 在函数内部工作吗?
答案 0 :(得分:5)
exec()
接受globals
的第二个参数。如docs中所述:
注意:内置函数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()
答案 1 :(得分:2)
Kevin的评论很好,并且需要重复一遍-使用exec很危险,几乎总是有更好的方法。
但是,在第一种情况下,针对您的问题,f1()和f2()都位于全局命名空间中,因此当您调用f2()时,它可以找到f1()。在第二种情况下,它们是在foo()函数的本地空间中创建的。调用f2()时,找不到本地f1()定义。
您可以使用以下方法解决此问题:
code = """
global f1
def f1(): print "bar"
def f2(): f1()
"""
def foo():
exec(code)
f2()
foo()
再次-这几乎肯定不是您要解决此问题的方法。
**编辑**发布了我一直在检查的错误版本的代码,这个版本是我本应包含的。
答案 2 :(得分:-1)
“在所有情况下,如果省略[exec()的可选部分),则代码将在当前作用域中执行。”