Python函数变量绑定问题:循环添加lambda时如何绑定当前迭代i值
问题原因
Python 中闭包的变量是晚绑定的:闭包内部用到的外部变量,只会在函数实际调用的时候才会查询取值,而非函数定义时就固定下来。你遇到的就是典型的循环内定义闭包的绑定问题,所有lambda调用时读取的都是循环结束后最终的i值。
解决方案
最简便的方式是利用「函数默认参数在定义阶段求值」的特性,给lambda添加一个默认参数来捕获当前迭代的i值:
把追加函数的行修改为:
func_list.append(lambda x, i=i: x*i)
此时每次迭代创建lambda时,都会把当前的i值作为默认参数绑定到函数的形参i上,后续i的更新不会影响已经创建好的函数的默认参数值。
你也可以用functools.partial实现同样的绑定效果:
from functools import partial # ... 其余代码不变 func_list.append(partial(lambda x, i: x*i, i=i))
修正后完整运行代码
import matplotlib.pyplot as plt import numpy as np func_list = [] for i in range(1, 4): func_list.append(lambda x, i=i: x*i) d = np.linspace(0, 5) for func in func_list: plt.plot(d, func(d)) plt.grid() plt.show()
运行后即可得到斜率分别为1、2、3的三条直线。
说明为什么之前的方法无效
你尝试用内存地址取值的方案仍然无效,本质是因为ctypes.cast(id(i), ctypes.py_object).value这段代码是在lambda调用时才执行的,此时i已经是循环结束后的3,不管你是直接取i的值还是取i对应地址的值,拿到的都是最终的3,自然无法实现绑定当前迭代值的效果。
内容的提问来源于stack exchange,提问作者Gabe Morris
相关产品推荐
相关产品推荐

