使用带递归函数的exec()

时间:2009-05-16 07:21:26

标签: python recursion exec

我想执行一些Python代码,在运行时键入,所以我得到字符串并调用

  

exec(pp,globals(),locals())

其中 pp 是字符串。它的工作正常,除了递归调用,e。例如,这段代码没问题:

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:全局名称'horse'不是   定义

还有办法运行递归代码吗?

更新

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:未定义全局名称'rec'

4 个答案:

答案 0 :(得分:4)

它对我有用:

a = """\
def rec(n):
    if n > 10:
        return
    print n
    return rec(n+1)

rec(5)"""

exec(a)
5
6
7
8
9
10

我只能说你的代码中可能存在错误。

修改

你去吧

def fn1():
    glob = {}
    a = """\
def rec(n):
    if n > 10:
        return
    print n
    return rec(n+1)

rec(5)"""
    exec(a, glob)

fn1()

答案 1 :(得分:4)

这一开始让我感到惊讶,似乎是一个奇怪的角落,其中exec的行为既不像顶级定义,也不是封闭函数中的定义。看起来正在发生的是函数定义是在传入的locals()dict中执行的。但是,定义的函数实际上不能访问这个本地dict。

通常,如果在顶层定义一个函数,则locals和globals是相同的,因此函数在内部可见,因为它们可以在全局变量中看到函数。

当一个函数在另一个函数的作用域内定义时,python会注意到它在函数内被访问,并创建一个闭包,以便“horse”映射到外部作用域中的绑定。

在这里,这是一个奇怪的中途案例。 exec的行为就好像定义位于顶层,因此不会创建闭包。但是,由于locals与globals不同,因此该定义不会进入函数可以访问它的位置 - 它仅在不可访问的外部本地dict中定义。

你可以做几件事:

  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

  4. 的建议,强制函数进入globals()而不是本地,方法是设置“global funcname”指令。

答案 2 :(得分:3)

这对我有用(添加global rec)。 rec(5)调用本地rec,但rec(n+1)调用全局rec(不存在),不带它。

def fn1():
    a = """global rec
def rec(n):
    if n > 10:
        return
    print n
    return rec(n+1)

rec(5)"""

    exec(a)

答案 3 :(得分:0)

“NameError:未定义全局名称'rec'”意味着它在全局范围内寻找rec,而不是本地范围。看起来它在本地范围内定义rec,然后尝试在全局范围内执行。尝试在正在执行的字符串旁边打印locals()和globals()。

More info.