在此代码中,lambda中的x指的是for语句中的x。所以y[0]()
会返回2:
x = 0
y = [lambda : x for x in range(3)]
y[0]()
但是在这段代码中,lambda中的x指的是全局x,所以x[0]()
返回全局x本身:
x = [lambda : x for x in range(3)]
x[0]()
我想知道为什么lambda中的x引用第一段代码中的局部x而第二段代码中的全局x。
答案 0 :(得分:6)
我猜你是在python 2.x上,在列表解析中,临时变量'泄漏'进入命名空间。您可以在this blog post from Guido中了解原因。
在Python 2中,列表推导“泄漏”循环控制变量 进入周围的范围......这是原始的神器 列表推导的实施;这是Python的一个“肮脏的 小秘密“多年。
这已在python 3中修复。
我不确定为什么你会混淆lambda
的内容,在这个简单的情况下你会看到相同的行为:
>>> x = 'a'
>>> y = [x for x in 'b','c']
>>> x
'c'
>>> x = [x for x in 'b','c']
>>> x
['b', 'c']
答案 1 :(得分:5)
x
指的是两段代码中的全局x
。实际上,在两段代码中都没有但全局x
。这里没有局部变量,只有全局变量。
在第一个示例中,x
的全局值为2,因为这是列表推导分配给它的最后一个值。列表推导将其变量泄漏到封闭范围内,如@wim所述。由于此处的封闭范围是全局范围,因此变量x
会泄漏到全局范围,覆盖您之前设置的值0.
在第二个示例中,您创建列表推导,但随后将其值分配给(全局)变量x。这会覆盖x中已有的内容,因此全局变量x的值现在是列表。
在这两种情况下,当您调用列表中的一个函数(任何一个!)时,它将返回当前值x
。你可以在这里看到:
>>> y = [lambda : x for x in range(3)]
>>> y[0]()
2
>>> x = 88
>>> y[0]()
88
>>> x = [lambda : x for x in range(3)]
>>> y = x
>>> y[0]()
[<function <lambda> at 0x017789B0>,
<function <lambda> at 0x01828DB0>,
<function <lambda> at 0x01828F30>]
>>> x = 88
>>> y[0]()
88
答案 2 :(得分:2)
>>> x='a'
>>>x = [lambda : x for x in range(3)]
一旦迭代开始,x
被分配给0
,从range()
返回(并且删除了对'a'的引用)。在最后一次迭代中,x
的值变为2,一旦LC退出,LC就会被分配到x
,所以现在x
指向LC。
示例:
>>> [x for x in range(3)]
[0, 1, 2]
>>> x
2
>>> x=[x for x in range(3)]
>>> x
[0, 1, 2]