Python中迭代创建lambda:为何一种方法有效另一种无效?
我尝试为字典中的每个键批量创建lambda函数,而非逐个手动创建。最终我实现了需求,但想理解为何第一种方法无效,第二种却有效——我原本以为两者结果一致,不清楚问题出在哪!
以下是简化示例:
方法1:直接在循环中创建Lambda
# approach 1 ======================================== bunch_of_funcs = { "func1": None, "func2": None, "func3": None, "func4": None, } for func_name in bunch_of_funcs: bunch_of_funcs[func_name] = lambda: print(func_name) # 执行后...连续打印4次func4 for func in bunch_of_funcs.values(): func()
方法2:通过辅助函数创建Lambda
# approach 2 ======================================== def lambda_func(func_name): return lambda: print(func_name) for func_name in bunch_of_funcs: bunch_of_funcs[func_name] = lambda_func(func_name) # 执行后...输出符合预期 for func in bunch_of_funcs.values(): func()
编辑补充
在看到回答后,我尝试通过将for循环封装在函数中来“本地化”变量,但结果仍相同……这个变量是在哪创建的?为何每次迭代都会被修改?我的修改如下:
def make_lambdas(dict_of_funcs): for func_name in dict_of_funcs: dict_of_funcs[func_name] = lambda: print(func_name) make_lambdas(bunch_of_funcs)
问题核心:Lambda的变量延迟绑定
Lambda表达式并不会在定义时捕获变量的当前值,而是在调用时才去查找变量的当前值。
方法1失效的原因:
循环中的func_name是同一个变量,每次迭代只会更新它的值。所有创建的lambda都引用这同一个变量,当循环结束后,func_name的最终值是"func4",因此所有lambda调用时都会打印这个值。方法2有效的原因:
辅助函数lambda_func每次被调用时,都会创建一个局部变量func_name,这个变量的值是当前迭代传入的参数。每个lambda捕获的是各自对应的局部变量,这些变量的值在函数调用时就被固定下来,不会随后续迭代改变,因此调用时能输出正确的键名。封装函数后仍失效的原因:
即使把循环放进函数make_lambdas里,循环变量func_name依然是该函数内的同一个变量,所有lambda还是引用它。循环结束后func_name依然是最后一个键,所以调用结果还是一致的。
快速解决方法(无需辅助函数)
如果不想用辅助函数,可以通过默认参数在定义时捕获变量的当前值:
for func_name in bunch_of_funcs: bunch_of_funcs[func_name] = lambda func_name=func_name: print(func_name)
默认参数的值会在lambda定义时就被计算并绑定,这样每个lambda都持有自己独立的func_name值,调用时就能输出正确结果。
内容的提问来源于stack exchange,提问作者Bruno Reis

