为何Python中multipliers函数返回的lambda调用结果均为3而非[0,1,2,3]?
为什么所有lambda里的i都是3?
这是个超经典的Python闭包陷阱!核心问题在于lambda捕获的是变量的引用,而非循环时变量的当前值。
你看,multipliers()里的列表推导式在循环for i in range(4)时,每个lambda并没有立刻把当时的i值存下来,只是记住了“i这个变量”的位置。等你后面调用m(1)的时候,循环早就跑完了——这时候i的值已经变成3了,所以每个lambda调用时,都会去取这个已经变成3的i来计算,结果自然全是3*1=3。
怎么解决这个问题?
有两种常用的办法,都能帮你把循环时的i值固定下来:
1. 用默认参数绑定当前值
把lambda改成lambda x, i=i: i * x,这样在创建lambda的瞬间,就会把当时的i值作为默认参数绑定进去,每个lambda都拥有自己独立的i副本:
def multipliers(): return [lambda x, i=i: i * x for i in range(4)] print([m(1) for m in multipliers()]) # 输出 [0, 1, 2, 3]
2. 使用functools.partial
用partial提前把i的值绑定到函数上,相当于给每个函数预先固定好乘数:
from functools import partial def multipliers(): return [partial(lambda i, x: i * x, i) for i in range(4)] print([m(1) for m in multipliers()]) # 输出 [0, 1, 2, 3]
总结一下:闭包记住的是变量的“位置”,不是当时的数值,所以要想办法在创建函数的那一刻把值固定住,别等调用的时候再去拿变量的最新值。
内容的提问来源于stack exchange,提问作者Alexey
相关产品推荐
相关产品推荐

