最近,我开始使用Python,我发现闭包的工作方式有些奇怪.考虑下面的代码:
adders=[None, None, None, None]
for i in [0,1,2,3]:
adders[i]=lambda a: i+a
print adders[1](3)
它构建了一个简单的函数数组,这些函数接受一个输入并返回加上一个数字的输入.在for
循环中构造函数,其中迭代器i
从0
运行到3
.对于这些数字中的每一个,都创建了一个lambda
函数,该函数捕获i
并将其添加到函数的输入中.最后一行使用3
作为参数调用第二个lambda
函数.令我惊讶的是,yields 是6
.
我原以为是4
分.我的推理是:在Python中,一切都是对象,因此每个变量都是指向它的指针.在为i
创建lambda
个闭包时,我预计它会存储一个指向i
当前指向的整数对象的指针.这意味着当i
分配一个新的整数对象时,它应该不会影响之前创建的闭包.遗憾的是,判断调试器中的adders
数组会发现确实如此.所有lambda
个函数都引用最后一个值i
,3
,这会导致adders[1](3)
返回6
.
这让我想知道:
- 闭包到底捕获了什么?
- 说服
lambda
个函数捕捉i
当前值的最优雅方式是什么?当i
改变其值时,这种方式不会受到影响?