为什么 eval 找不到在外部函数中定义的变量?

Why can't eval find a variable defined in an outer function?

我知道使用 eval() 通常意味着错误的代码,但我偶然发现 eval() 函数在内部函数中有一种我无法理解的奇怪行为。如果我们写:

def f(a):
    def g():
        print(eval('a'))
    return g()

运行 f(1) 在这种情况下产生 NameError,声称 a 未定义。但是,如果我们定义

def f(a):
    def g():
        b = a + 1
        print(eval('a'))
    return g()

然后 运行 f(1) 打印 1

局部变量和全局变量发生了一些我不太明白的事情。 a 只是 g() 中的局部变量,而 "used" 是什么东西?这是怎么回事?

简而言之,由于eval是动态计算的,解释器无法知道它应该将a添加到g的本地范围。为了效率,解释器不会在局部变量的dict中添加不需要的变量。

来自 eval 的文档:

The expression argument is parsed and evaluated as a Python expression (technically speaking, a condition list) using the globals and locals dictionaries as global and local namespace.

这意味着函数 eval(expression) 将使用 globals() 作为其默认全局范围,如果提供 none 则使用 locals() 作为其本地范围。

虽然,在你的第一个例子中 a 两者都不在。

def f(a):
    print("f's locals:", locals())
    def g():
        print("g's locals:", locals())
        print(eval('a'))
    return g()

f(1)

确实,由于解释器在解析 g 的主体时没有看到对 a 的引用,因此不会将其添加到其局部变量中。

要使其正常工作,您需要在 g 中指定 nonlocal a

输出

f's locals: {'a': 1}
g's locals: {}
Traceback ...
...
NameError: name 'a' is not defined

在您的第二个示例中,ag 局部变量中,因为它在范围内使用。

def f(a):
    print("f's locals:", locals())
    def g():
        print("g's locals:", locals())
        b = a + 1
        print("g's locals after b = a + 1:", locals())
        print(eval('a'))
    return g()

f(1)

输出

f's locals: {'a': 1}
g's locals: {'a': 1}
g's locals after b = a + 1: {'a': 1, 'b': 2}
1

看起来 eval() 只能在本地(此处,g)或全局中查找变量,而不能在其父环境(此处为 f)中查找。四处走动是将变量设置为全局变量。

 
def f(a):    
    global b #note, can not use "global a" directly,  will get error:"name 'a' is parameter and global"
    b=a
    def g():
        print(eval('b'))
    return g()
f(1)

输出:1