我知道使用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()
中用于某些用途时是局部变量吗?这是怎么回事?
答案 0 :(得分:4)
简而言之,由于eval
用于动态求值,解释器无法知道应该将a
添加到g
的本地范围中。为了提高效率,解释器不会将不需要的变量添加到局部变量dict
中。
来自eval
的文档:
expression参数将使用globals和locals字典作为global和local名称空间解析并评估为Python表达式(从技术上来说是条件列表)。
这意味着函数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)
实际上,由于解释器在解析a
的主体时看不到对g
的引用,因此不会将其添加到其局部变量中。
要使其正常工作,您需要在nonlocal a
中指定g
。
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
答案 1 :(得分:0)
看起来eval()只能在local(here,g)或global中查找变量,而不能在其父环境(此处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