简而言之,由于
eval
是用于动态评估的,解释器无法知道它应该将
a
添加到
g
的局部作用域中。为了提高效率,解释器不会将不需要的变量添加到局部变量的
dict
中。
根据
eval
文档:
表达式参数将使用全局和本地命名空间字典作为全局和本地范围进行解析和评估(严格来说是条件列表)。
这意味着如果没有提供全局和本地作用域,则函数
eval(expression)
将使用
globals()
作为其默认全局作用域,
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
在你的第二个示例中,
a
在
g
的本地变量中,因为它在该作用域中被使用。
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