我想执行一些在运行时键入的 Python 代码,所以我获取字符串并调用
exec(pp, globals(), locals())
其中 pp 是字符串。它工作正常,除了递归调用,e。 g. 比如这段代码就可以了:
def horse():
robot.step()
robot.step()
robot.turn(-1)
robot.step()
while True:
horse()
但这一个不是:
def horse():
robot.step()
robot.step()
robot.turn(-1)
robot.step()
horse()
horse()
NameError: global name 'horse' is not defined
是否也有运行递归代码的方法?
更新
a = """\
def rec(n):
if n > 10:
return
print n
return rec(n+1)
rec(5)"""
exec(a)
如果放在顶层就可以工作。但是如果在函数内部移动:
def fn1():
a = """\
def rec(n):
if n > 10:
return
print n
return rec(n+1)
rec(5)"""
exec(a)
fn1()
出现同样的错误:NameError: global name 'rec' is not defined
最佳答案
起初这也让我感到惊讶,并且似乎是一个奇怪的极端情况,其中 exec 的行为既不像顶级定义,也不像封闭函数中的定义。看起来正在发生的事情是函数定义正在您传入的 locals() dict 中执行。但是,定义的函数实际上并没有访问这个 locals dict。
通常,如果您在顶层定义一个函数,则局部变量和全局变量是相同的,因此函数在内部是可见的,因为它们可以在全局变量中看到该函数。
当一个函数在另一个函数的范围内定义时,python 会注意到它在函数内被访问,并创建一个闭包,以便“马”映射到外部范围内的绑定(bind)。
在这里,这是一个奇怪的中途案例。 exec 就像定义在顶层一样,所以没有创建闭包。然而,由于局部变量与全局变量不同,定义不会出现在函数可以访问它的地方 - 它仅在不可访问的外部局部变量字典中定义。
您可以做几件事:
- 对局部变量和全局变量使用相同的字典。即“
exec s in locals(),locals()
”(或者更好,只使用您自己的字典)。仅提供 globals() dict 具有相同的效果 - 即“exec s in mydict
” # 将 func 放在它自己的函数中,这样就创建了一个闭包。例如
s=""" def go(): def factorial(x): if x==0: return 1 return x*factorial(x-1) print factorial(10) go()"""
按照 stephan's answer 的建议,通过放置“global funcname”指令强制函数进入 globals() 而不是局部变量。
关于python - 将 exec() 与递归函数一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/871887/