正如Wooble所说,问题是类没有词法范围(实际上,在Python 2或{a2})中。相反,它们有一个不构成作用域的局部命名空间。这意味着类定义中的表达式可以访问命名空间的内容:class C:
a = 2
b = a + 2 # b = 4
但是类主体中引入的作用域不能访问其命名空间:
^{pr2}$
Python2和Python3的区别在于,在Python2中,列表理解引入了一个新的范围:[a for a in range(3)]
print a # prints 2
而在Python 3中则是:[a for a in range(3)]
print(a) # NameError: name 'a' is not defined
在python3中,这一点有两个原因,包括使列表理解的行为方式与生成器表达式(genexps)相同;(a for a in range(3))在python2和python3中都有自己的作用域。在
因此,在类的主体中,python2genexp或python3listcomp或genexp引入了一个新的作用域,因此不能访问类定义本地名称空间。在
让genexp/listcomp访问类定义命名空间中的名称的方法是使用函数或lambda引入一个新的作用域:class C:
a = 2
b = (lambda a=a: [a + i for i in range(3)])()
eval问题
您的eval示例的问题是,eval默认情况下在本地作用域中计算其参数;因为Python 2列表理解具有共享封闭作用域的上述行为,eval可以访问方法作用域,但是genexp或python3listcomp本地作用域只具有编译器可以判断出需要的任何内容封闭作用域(因为genexp/listcomp作用域是闭包):def bar(x):
return list(eval('x') + x for i in range(3))
bar(5) # returns [10, 10, 10]
def baz(x):
return list(eval('x') for i in range(3))
baz(5) # NameError: name 'x' is not defined
正如Martijn所说,您应该使用getattr,而不是eval。在