这个问题已在Python 3中得到解决。当您使用列表推导式[i(0) + i(1) for a in alist]
时,您将在其周围的作用域中定义a
,该作用域对i
是可访问的。在新会话list(i(0) + i(1) for a in alist)
将会抛出错误。
>>> i = lambda x: a[x]
>>> alist = [(1, 2), (3, 4)]
>>> list(i(0) + i(1) for a in alist)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <genexpr>
File "<stdin>", line 1, in <lambda>
NameError: global name 'a' is not defined
列表推导式不是生成器:
生成器表达式和列表推导式。
引用块:
生成器表达式用圆括号“()”括起来,而列表推导式用方括号“[]”括起来。
在您的例子中,作为一个类的
list()
有它自己的变量范围,并且最多可以访问全局变量。当您使用它时,
i
将在该范围内查找
a
。在新会话中尝试此操作。
>>> i = lambda x: a[x]
>>> alist = [(1, 2), (3, 4)]
>>> [i(0) + i(1) for a in alist]
[3, 7]
>>> a
(3, 4)
将其与另一个会话中的内容进行比较:
>>> i = lambda x: a[x]
>>> alist = [(1, 2), (3, 4)]
>>> l = (i(0) + i(1) for a in alist)
<generator object <genexpr> at 0x10e60db90>
>>> a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> [x for x in l]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <genexpr>
File "<stdin>", line 1, in <lambda>
NameError: global name 'a' is not defined
当你运行
list(i(0) + i(1) for a in alist)
时,你将传递一个生成器
(i(0) + i(1) for a in alist)
给
list
类,在其自己的范围内尝试将其转换为列表后返回。对于这个生成器来说,它在lambda函数内部没有任何访问权限,变量
a
没有意义。
生成器对象<generator object <genexpr> at 0x10e60db90>
已经失去了变量名a
。然后当list
尝试调用生成器时,lambda函数会因未定义的a
而抛出错误。
与生成器相比,列表推导式的行为也在此处提到:here:
列表推导式也将它们的循环变量“泄漏”到周围的作用域中。这也将在Python 3.0中发生改变,使得Python 3.0中列表推导式的语义定义等同于列表()。Python 2.4及以上版本应该如果列表推导式的循环变量与紧邻的环境中使用的变量具有相同的名称,则发出弃用警告。
在Python3中:
>>> i = lambda x: a[x]
>>> alist = [(1, 2), (3, 4)]
>>> [i(0) + i(1) for a in alist]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <listcomp>
File "<stdin>", line 1, in <lambda>
NameError: name 'a' is not defined
NameError: global name 'a' is not defined
。 - Himanshu Mishra