Python 使用方法理解列表中的评估范围

Python 使用方法理解列表中的评估范围,python,function,list-comprehension,eval,Python,Function,List Comprehension,Eval,我对列表理解和eval语句相结合的方法感到困惑。test7行中的以下代码出现错误,错误为NameError:name“a2” class test_class(object): def __init__(self): pass @property def property(self): return 'test_method_run' def run(): a2 = test_class() test3 = eval('a

我对列表理解和
eval
语句相结合的方法感到困惑。test7行中的以下代码出现错误,错误为
NameError:name“a2”

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()
它一定与scope()有关。我对Python2中作用域的理解(我刚刚转到Python3)是
a
不应该在
run()
中定义,而
a2
是。列表理解的影响使我更加困惑。我的期望是
test2
test3
行应该失败,因为
a
没有使用
test
方法定义。我还希望如果
test5
运行正常,那么
test6
test7
也应该可以

只有在函数中的列表理解中使用了
eval
时,才会发生此错误。。。如果这3个元素中的任何一个不存在,则没有错误。我的问题是为什么?我觉得我没有足够的理解来形成一个更好的问题

我对Python2中的作用域的理解(我刚刚转到Python3)是不应该在run()中定义a,而应该在a2中定义

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之间的唯一变化。(如果不是,这是唯一与此场景相关的更改。)

Python 3中作用域的另一个更改是
非局部
语句的可用性,它允许内部函数修改外部函数作用域中定义的变量。但正如你所说,这与这个问题无关。