你的第二个问题已经回答了,但是你的第一个问题:
what does the closure capture exactly?
Python中的范围是动态和词法的。闭包将永远记住变量的名称和范围,而不是它指向的对象。由于您示例中的所有函数都在同一作用域中创建,并使用相同的变量名,因此它们始终引用相同的变量。
编辑:关于你的另一个如何克服这个问题,有两种方式来想:
>最简洁但不完全等效的方法是one recommended by Adrien Plisson.创建一个带有额外参数的lambda,并将extra参数的默认值设置为要保留的对象。
>稍微冗长一些,但不太好用的就是每次创建lambda时创建一个新的范围:
>>> adders = [0,1,2,3]
>>> for i in [0,1,2,3]:
... adders[i] = (lambda b: lambda a: b + a)(i)
...
>>> adders[1](3)
4
>>> adders[2](3)
5
这里的范围是使用一个新函数(一个lambda,为了简洁)创建的,它绑定其参数,并传递要绑定的值作为参数。在实际代码中,你很可能有一个普通的函数,而不是lambda来创建新的范围:
def createAdder(x):
return lambda y: y + x
adders = [createAdder(i) for i in range(4)]