你的第二个问题已得到解答,但至于你的第一个问题:
what does the closure capture exactly?
Python中的范围是动态的和词汇的.闭包将始终记住变量的名称和范围,而不是它指向的对象.由于示例中的所有函数都在同一作用域中创建并使用相同的变量名,因此它们始终引用相同的变量.
编辑:关于如何克服这个问题的另一个问题,有两种方法可以想到:
>最简洁但不严格等效的方法是one recommended by Adrien Plisson.创建一个带有额外参数的lambda,并将额外参数的默认值设置为要保留的对象.
>每次创建lambda时,创建一个新范围会更冗长但更少hacky:
>>> 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)]