Python递归函数上的 AST exec“...未定义”错误
Python AST exec "... is not defined" error on recursive function
我遇到了这个错误
def test_rec():
import ast
exec(compile(ast.fix_missing_locations(ast.parse("""
def fact(n):
return 1 if n == 0 else n * fact(n - 1)
print(fact(5))
"""), "<string>", "exec")))
这会产生这个错误,这很奇怪
Traceback (most recent call last):
File "/Users/gecko/.pyenv/versions/3.9.0/envs/lampy/lib/python3.9/site-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/Users/gecko/code/lampycode/tests/test_let_lang.py", line 6, in test_rec
exec(compile(ast.fix_missing_locations(ast.parse("""
File "<string>", line 4, in <module>
File "<string>", line 3, in fact
NameError: name 'fact' is not defined
如果我在 REPL 中复制并粘贴相同的代码,它可以正常工作
>>> def fact(n):
... return 1 if n == 0 else n * fact(n - 1)
...
>>> print(fact(5))
120
>>>
有什么想法吗?
我可以进一步减少这个问题,这里是最小的例子,这会溢出堆栈,但它给我同样的未定义错误
def test_rec3():
exec("""
def f():
f()
f()
""")
--
第二次编辑,更进一步,这只发生在函数内部
这个有效
exec("""
def f(n):
print("end") if n == 1 else f(n-1)
f(10)""")
但这给了我和上面一样的错误
def foo():
exec("""
def f(n):
print("end") if n == 1 else f(n-1)
f(10)""")
foo()
如果您将 exec
与默认局部变量一起使用,则绑定局部变量是未定义的行为。其中包括 def
,它将新函数绑定到局部变量。
此外,在 exec
中定义的函数不能访问闭包变量,而 fact
可以。
避免这些问题的最好方法是不使用 exec
。第二种最好的方法是提供一个明确的命名空间:
namespace = {}
exec(whatever, namespace)
我遇到了这个错误
def test_rec():
import ast
exec(compile(ast.fix_missing_locations(ast.parse("""
def fact(n):
return 1 if n == 0 else n * fact(n - 1)
print(fact(5))
"""), "<string>", "exec")))
这会产生这个错误,这很奇怪
Traceback (most recent call last):
File "/Users/gecko/.pyenv/versions/3.9.0/envs/lampy/lib/python3.9/site-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/Users/gecko/code/lampycode/tests/test_let_lang.py", line 6, in test_rec
exec(compile(ast.fix_missing_locations(ast.parse("""
File "<string>", line 4, in <module>
File "<string>", line 3, in fact
NameError: name 'fact' is not defined
如果我在 REPL 中复制并粘贴相同的代码,它可以正常工作
>>> def fact(n):
... return 1 if n == 0 else n * fact(n - 1)
...
>>> print(fact(5))
120
>>>
有什么想法吗?
我可以进一步减少这个问题,这里是最小的例子,这会溢出堆栈,但它给我同样的未定义错误
def test_rec3():
exec("""
def f():
f()
f()
""")
--
第二次编辑,更进一步,这只发生在函数内部
这个有效
exec("""
def f(n):
print("end") if n == 1 else f(n-1)
f(10)""")
但这给了我和上面一样的错误
def foo():
exec("""
def f(n):
print("end") if n == 1 else f(n-1)
f(10)""")
foo()
如果您将 exec
与默认局部变量一起使用,则绑定局部变量是未定义的行为。其中包括 def
,它将新函数绑定到局部变量。
此外,在 exec
中定义的函数不能访问闭包变量,而 fact
可以。
避免这些问题的最好方法是不使用 exec
。第二种最好的方法是提供一个明确的命名空间:
namespace = {}
exec(whatever, namespace)