我对结合列表理解和eval
语句的方法感到困惑。下面的代码在test7行上错误,错误为NameError: name 'a2' is not defined
。
class test_class(object):
def __init__(self):
pass
@property
def property(self):
return 'test_method_run'
def run():
a2 = test_class()
test3 = eval('a.property')
test4 = [eval('a.property') for i in range(10)]
test5 = eval('a2.property')
test6 = [a2.property for i in range(10)]
test7 = [eval('a2.property') for i in range(10)
a = test_class()
test1 = eval('a.property')
test2 = [eval('a.property') for i in range(10)]
run()
它必须与范围(eval fails in list comprehension)有关。我对python 2(我刚刚移至python 3)范围的理解是,a
不应在run()
中定义,而a2
是应该定义的。列表理解的影响使我更加困惑。我的期望是test2
和test3
行应该失败,因为a
没有用test
方法定义。我还希望如果test5
运行正常,那么test6
和test7
也应该没问题。
仅当在函数内的列表理解中使用eval
时,才会发生此错误...如果这三个元素中的任何一个都不存在,则没有错误。我的问题是为什么?我觉得我不太了解它,无法提出一个更好的问题。
答案 0 :(得分:3)
我对python 2(我刚刚移至python 3)范围的理解是,不应在run()中定义a,而应在a2中定义a。
a
中的a2
和run
都是可见的。 a
是在全局范围内定义的,因此在该文件的任何位置都可见。
我希望如果test5运行正常,那么test6和test7也应该没问题。
在3.X中,列表推导具有自己的范围。 test6列表理解可以访问三个范围:列表理解的范围,函数的范围和全局范围。因此它可以访问i
和a2
和a
。
默认情况下,在eval
内部执行的代码可以访问两个范围:全局范围和最接近的本地范围。这意味着test7
eval可以访问在文件级别定义的变量,并且可以访问在列表理解范围内定义的变量,但不能访问在函数内部定义但在列表理解范围之外的变量。它可以看到a
和i
,但看不到a2
。
在2.7中,列表推导没有得到自己的范围。它们与定义的函数具有相同的作用域。这说明了为什么您的代码在2.7中执行但不在3.X中执行。 IIRC,这是在2.7和3.X之间对示波器系统进行的唯一更改。 (如果不是,那么这是唯一与此场景有关的更改。)