延迟绑定()闭包
中的一个常见困惑是闭包(或在周围全局作用域())中绑定变量的方式问题。
你写的函数:
你期望的:
一个包含了五个函数返回值的列表,每个函数有它们自己的封闭变量乘以它们的参数,得到:
而实际结果是:
它创建了五个函数,但是它们全都是乘以。的闭包是迟绑定。这意味着闭包中用到的变量的值是在内部函数被调用时查询得到的。 在这里, 每当调用任何函数返回时,的值是调用时在周围作用域()中查询到的。到那个时候,循环已经完成,的值最终变成。 关于这个陷阱有一个普遍严重的误解,它很容易被甩锅给的lambda表达式。实际上,表达式是被冤枉滴。
我们尝试把它改写成普通函数:
为了实现目标,你应该这样:
1. 最一般的解决方案可以说是有点取巧()。由于拥有在前文提到的为函数默认参数赋值的行为(参见可变默认参数),你可以像下面这样创建一个立即绑定参数的闭包:
2. 或者,你可以使用函数(偏函数):
3. 优雅的写法,直接用生成器表达式:
4. 利用的惰性求值思想编写生成器函数:
当陷阱不是一个陷阱
有时, 你预期闭包是这样的(迟绑定的表现形式)。延迟绑定在多数情况下是正常的。不幸的是, 循环创建独特的函数可能会导致未知的小问题。
派森多一点
关于生成器的惰性求值,我们可以看点简单的例子:
返回结果:
如果我们对之前改写的函数再稍微改写一下,让内部函数传值会怎么样?
返回结果:
实际上,相当于一个生成器推导式,这点很容易验证:
外链:
[lambda表达式](http://docs.python.org/reference/expressions.html#lambda)
[可变默认参数](http://docs.python-guide.org/en/latest/writing/gotchas/#default-args)
领取专属 10元无门槛券
私享最新 技术干货