繁体   English   中英

Python3:将递归 function 注入到 function 中的 exec() 中

[英]Python3: inject a recursive function into exec() in a function

在 python3 中,如果将带有递归调用的 function 注入到 function 中的exec()中,则会出现错误。 例如,下面的代码

def B(pys):
    exec(pys)

pys="""
def fibonacci(n):
    if n == 1 or n == 2:
        r = 1
    else:
        r = fibonacci(n - 1) + fibonacci(n - 2)
    return r

print(fibonacci(3))
"""
B(pys)

将引发 NameError。

$ py -3.8 testrecursivefun.py
Traceback (most recent call last):
  File "testrecursivefun.py", line 14, in <module>
    B(pys)
  File "testrecursivefun.py", line 2, in B
    exec(pys)
  File "<string>", line 9, in <module>
  File "<string>", line 6, in fibonacci
NameError: name 'fibonacci' is not defined

如果我直接在模块下运行 exec(pys) ,异常就消失了。

原因已在另一个问题中描述过exec 如何与当地人合作? . 但我仍然不知道如何弄清楚exec()中的递归调用。 因为 function 名称对我来说是动态的。 我不能将它添加到locals()exec() 谁能帮我弄清楚。

为了得到答案,您可以将代码包装在 function 中,因此递归 function 位于其本地 scope 中:

import textwrap

def B(pys):
    exec(pys, globals(), {})

pys="""
def fibonacci(n):
    if n == 1 or n == 2:
        r = 1
    else:
        r = fibonacci(n - 1) + fibonacci(n - 2)
    return r

print(fibonacci(11))
"""

def wrap(s):
    return "def foo():\n" \
           "{}\n" \
           "foo()".format(textwrap.indent(s, ' ' * 4))

B(wrap(pys))

通常,重新考虑使用 exec。

我实际上对你的问题很感兴趣,所以我开始研究这个话题。 似乎解决您的问题的简单方法是:

  1. 首先使用compile function in python 将字符串编译为代码
  2. 然后使用exec function 执行编译后的代码

这是示例解决方案:

psy="""
def fibonacci(n):
    if n == 1 or n == 2:
        r = 1
    else:
        r = fibonacci(n - 1) + fibonacci(n - 2)
    return r

print(fibonacci(3))
"""

def B(psy):
    code = compile(psy, '<string>', 'exec')
    exec(code, globals())

B(psy)

这里 compile 需要三个参数:

首先是字符串格式的代码,其次是我们使用的文件名提示因为我们将字符串作为代码本身,第三个可以是'exec'、'eval' 和 'single'之一。

链接包含有关如何在 python 中使用 exec 和 eval 的详细说明。 请检查它们以获取详细说明。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM