循环绑定matplotlib回调时Lambda传参 调用结果一致问题求解
问题原因
Python 中的闭包(你代码里用到的匿名lambda函数就属于闭包)采用迟绑定机制:闭包内引用的外部变量,只会在闭包实际被调用的时候才去查询变量的当前值,而非在闭包定义时就保存变量的瞬时值。
你的循环执行完成后,变量k的最终取值为"B",后续任意画布触发点击回调时,lambda函数才会读取k的值,所以所有回调打印的结果都是"B"。
修复方法
方法1:利用lambda默认参数固定循环值
函数的默认参数会在函数定义阶段完成求值,你可以把当前循环的k作为lambda的默认参数传入,即可把每次迭代的k值绑定到对应回调上:
修改回调绑定的代码行为:
cid = fig.canvas.mpl_connect('button_press_event', lambda tmp, k=k: onclick(tmp, k))
完整可运行代码如下:
import matplotlib.pyplot as plt import numpy as np def onclick(event, key): print(key) for k in ["A", "B"]: x = np.arange(1,10) y = x**2 fig = plt.figure() ax = fig.add_subplot(111) ax.set_title(k) ax.plot(x,y) cid = fig.canvas.mpl_connect('button_press_event', lambda tmp, k=k: onclick(tmp, k)) plt.show()
方法2:使用functools.partial提前绑定参数
functools.partial可以创建偏函数,在实例化阶段就将指定参数绑定到目标函数上,不会受后续变量修改的影响,实现逻辑更清晰:
import matplotlib.pyplot as plt import numpy as np from functools import partial def onclick(event, key): print(key) for k in ["A", "B"]: x = np.arange(1,10) y = x**2 fig = plt.figure() ax = fig.add_subplot(111) ax.set_title(k) ax.plot(x,y) cid = fig.canvas.mpl_connect('button_press_event', partial(onclick, key=k)) plt.show()
内容的提问来源于stack exchange,提问作者HaMo
相关产品推荐
相关产品推荐

