Python中for循环内lambda表达式的i=i参数作用问询
为什么在for循环内定义lambda时需要用
i=i这种参数写法? 这个问题其实是Python中闭包延迟绑定导致的经典坑,我来给你掰扯清楚:
先看不用i=i会发生什么
假设你写了这样的代码:
def makeActions(): acts = [] for i in range(5): acts.append(lambda x: x**i) # 这里没写i=i return acts # 调用试试 funcs = makeActions() for f in funcs: print(f(2))
你可能以为会输出1, 2, 4, 8, 16(对应i=0到4时2的i次方),但实际输出是16,16,16,16,16——全是最后一次循环的i值(也就是4)的结果。
原因:闭包的延迟绑定
Lambda表达式是闭包,它不会在定义的时候就捕获当前i的值,而是在调用的时候才去查找i的当前值。当你循环结束后,所有lambda里的i都指向同一个变量(循环里的那个i),而此时i已经变成了4,所以所有lambda调用时都会用4来计算。
i=i的作用:参数默认值的即时绑定
那加上i=i之后为什么就正常了?
def makeActions(): acts = [] for i in range(5): acts.append(lambda x, i=i: x**i) # 这里的i=i return acts
这里的i=i是给lambda定义了一个带默认值的参数:
- 左边的
i是lambda的参数名 - 右边的
i是当前循环迭代中的i的值
Python在定义函数(包括lambda)时,会立即计算并保存参数默认值。所以每一次循环迭代时,lambda的i参数默认值都会被设置为当前循环的i的具体数值(0、1、2、3、4),而不是指向循环变量的引用。这样当后续调用lambda时,如果没有传入i,就会用这个预先保存的默认值,自然就能得到正确的结果。
另一种替代写法
除了用默认参数,你也可以用嵌套函数捕获当前值,原理是一样的:
def makeActions(): acts = [] for i in range(5): def helper(i): return lambda x: x**i acts.append(helper(i)) return acts
这里helper函数每次被调用时,都会把当前的i作为参数传入,捕获这个值后再返回对应的lambda,同样能避免延迟绑定的问题。
内容的提问来源于stack exchange,提问作者abctest
相关产品推荐
相关产品推荐

