Python循环生成Lambda函数列表出现值异常问题求助
循环中创建Lambda函数结果一致的问题解析
你这段代码里预期输出是2、4、6,但实际全是6,核心原因是Python的闭包(包括lambda)对外部变量的引用是延迟绑定的——不是在定义lambda的时候就把变量的当前值存下来,而是等到调用lambda的时候,才会去查找这个变量的当前值。
先贴出你的代码方便对照:
func = lambda a,x: a*x func_list = [] for i in range(3): __tmp = lambda x: (i+1)*x func_list.append(__tmp) x = 2 print(func_list[0](x)) print(func_list[1](x)) print(func_list[2](x))
问题根源拆解
在循环过程中,每次创建的lambda都只是引用了外部的变量i,并没有在定义时捕获i的当前值。当循环执行完毕后,i的值已经变成了2(因为range(3)会遍历0、1、2,最后一次循环结束后i停在2)。等到你调用func_list[0](x)这些函数的时候,lambda才会去取i的当前值——也就是2,所以每个函数计算的都是(2+1)*2=6,自然三个结果都一样。
几种可行的解决方案
方案1:用默认参数捕获当前变量值
在定义lambda的时候,给它加一个默认参数,把当前的i值绑定进去。默认参数的赋值是在lambda定义时完成的,这样每个lambda都会保存自己创建时的i值:
func_list = [] for i in range(3): __tmp = lambda x, i=i: (i+1)*x # 这里i=i把当前循环的i值绑定为默认参数 func_list.append(__tmp) x = 2 print(func_list[0](x)) # 输出2 print(func_list[1](x)) # 输出4 print(func_list[2](x)) # 输出6
方案2:使用functools.partial固定参数
functools.partial可以帮我们提前把参数绑定到函数上,避免闭包的延迟绑定问题:
from functools import partial func_list = [] for i in range(3): # 先定义一个带i参数的lambda,再用partial把当前的i绑定进去 __tmp = partial(lambda i, x: (i+1)*x, i) func_list.append(__tmp) x = 2 print(func_list[0](x)) # 输出2 print(func_list[1](x)) # 输出4 print(func_list[2](x)) # 输出6
方案3:用嵌套函数创建独立作用域
写一个专门生成函数的嵌套函数,通过参数传递当前的i值,这样每次调用这个嵌套函数时,都会创建一个独立的作用域保存i的值:
def create_multiplier(i): return lambda x: (i+1)*x func_list = [] for i in range(3): __tmp = create_multiplier(i) func_list.append(__tmp) x = 2 print(func_list[0](x)) # 输出2 print(func_list[1](x)) # 输出4 print(func_list[2](x)) # 输出6
内容的提问来源于stack exchange,提问作者space_voyager
相关产品推荐
相关产品推荐

