python - 将 exec() 与递归函数一起使用

标签 python recursion exec

我想执行一些在运行时键入的 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 就像定义在顶层一样,所以没有创建闭包。然而,由于局部变量与全局变量不同,定义不会出现在函数可以访问它的地方 - 它仅在不可访问的外部局部变量字典中定义。

您可以做几件事:

  1. 对局部变量和全局变量使用相同的字典。即“exec s in locals(),locals()”(或者更好,只使用您自己的字典)。仅提供 globals() dict 具有相同的效果 - 即“exec s in mydict” #
  2. 将 func 放在它自己的函数中,这样就创建了一个闭包。例如

    s="""
    def go():
        def factorial(x):
            if x==0: return 1
            return x*factorial(x-1)
        print factorial(10)
    go()"""
    
  3. 按照 stephan's answer 的建议,通过放置“global funcname”指令强制函数进入 globals() 而不是局部变量。

关于python - 将 exec() 与递归函数一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/871887/

相关文章:

python - 在 Keras 中,验证准确率始终高于训练准确率

recursion - 普通口齿不清 : error "CDR LST should be a lambda expression"

php - 我可以在 PHP 函数 exec() 中使用 linux 内置实用程序 compgen 吗?

c - 无法在 c 中使用 exec 和 makeargv 运行 ./program

java - 在 C++ 中 fork 一个新进程并执行一个 .jar 文件

python - 更新环境时出现 ValueError : not enough values to unpack (expected 2, 1)

python - 如何将多个项目设置到 GtkSelection 中以进行 Treeview 拖放

Python:用包含子字符串的单词拆分字符串

java - 为什么递归调用打印 '123456' 而不是 '1' ?

c++ - 使用基数排序检查索引