下面的代码显示 1
两次,但我希望看到 0
然后 1
.
def pv(v) :
print v
x = []
for v in range(2):
x.append(lambda : pv(v))
for xx in x:
xx()
我希望python lambdas在幕后绑定到局部变量所指向的引用。然而,情况似乎并非如此。我在一个大型系统中遇到了这个问题,其中lambda正在执行现代c++的绑定(例如boost::bind),在这种情况下,您将绑定到智能ptr或复制为lambda构建一个副本。
那么,如何将局部变量绑定到lambda函数,并使其在使用时保留正确的引用呢?这种行为让我目瞪口呆,因为我不希望这种语言使用垃圾收集器。
2条答案
按热度按时间7cjasjjr1#
改变
x.append(lambda : pv(v))
到x.append(lambda v=v: pv(v))
.您期望“python lambdas在幕后绑定到局部变量所指向的引用”,但python不是这样工作的。python在调用函数时查找变量名,而不是在创建函数时。使用默认参数是有效的,因为默认参数是在创建函数时计算的,而不是在调用函数时计算的。
这并不是lambdas的特别之处。考虑:
印刷品
btxsgosb2#
lambda的闭包保存对正在使用的变量的引用,而不是它的值,因此如果变量的值以后发生更改,闭包中的值也会发生更改。也就是说,闭包变量的值是在调用函数时解析的,而不是在创建函数时解析的(python在这里的行为在函数式编程世界中并不罕见,这是值得的。)
有两种解决方案:
使用默认参数,在定义时将变量的当前值绑定到本地名称。
lambda v=v: pv(v)
使用双lambda并立即调用第一个lambda。(lambda v: lambda: pv(v))(v)