以下测试失败:
#!/usr/bin/env python def f(*args): """ >>> t = 1, -1 >>> f(*map(lambda i: lambda: i, t)) [1, -1] >>> f(*(lambda: i for i in t)) # -> [-1, -1] [1, -1] >>> f(*[lambda: i for i in t]) # -> [-1, -1] [1, -1] """ alist = [a() for a in args] print(alist) if __name__ == '__main__': import doctest; doctest.testmod()
换一种说法:
>>> t = 1, -1 >>> args = [] >>> for i in t: ... args.append(lambda: i) ... >>> map(lambda a: a(), args) [-1, -1] >>> args = [] >>> for i in t: ... args.append((lambda i: lambda: i)(i)) ... >>> map(lambda a: a(), args) [1, -1] >>> args = [] >>> for i in t: ... args.append(lambda i=i: i) ... >>> map(lambda a: a(), args) [1, -1]
它们是不同的,因为i生成器表达式和list comp中的值都是惰性计算的,即在中调用匿名函数时f。 到那时,i如果绑定到最后一个值t-1。
i
f
t
因此,基本上,这就是列表理解的功能(对于genexp也是如此):
x = [] i = 1 # 1. from t x.append(lambda: i) i = -1 # 2. from t x.append(lambda: i)
现在,lambda携带了一个引用的闭包i,但i在两种情况下均绑定为-1,因为这是为其分配的最后一个值。
如果要确保lambda接收到的当前值i,请执行
f(*[lambda u=i: u for i in t])
这样,您i可以在创建闭包时强制进行评估。
编辑 :生成器表达式和列表推导之间有一个区别:后者将循环变量泄漏到周围的范围内。