Tkinter中for循环绑定按钮事件时所有按钮参数重复如何解决?
问题原因
这是Python闭包的延迟绑定特性导致的:匿名函数lambda作为闭包使用时,内部引用的外部循环变量i、j、letter不会在函数定义阶段就固定取值,只会在函数实际被调用(也就是你点击按钮)时才会查询变量的当前值。等你点击按钮时,两层for循环已经执行完毕,所有变量都停留在最后一次循环的赋值,因此所有按钮触发回调时拿到的都是最后一组参数。
修复方案
方案1:给lambda添加默认参数(最简单)
利用Python函数的默认参数会在函数定义时就计算赋值的特性,把每次循环的当前变量值固定到lambda的默认参数里,修改绑定逻辑即可:
# 仅修改bind这一行 btn.bind("<Button-1>", lambda e, current_i=i, current_j=j, current_letter=letter: self._boggle.moused_clicked(e, (current_i, current_j), current_letter))
方案2:用functools.partial预绑定参数(可读性更好)
通过functools.partial可以提前把固定参数绑定到回调函数上,避免lambda的变量捕获问题:
# 首先导入partial from functools import partial # 绑定逻辑修改为 btn.bind("<Button-1>", partial(lambda e, i, j, letter: self._boggle.moused_clicked(e, (i,j), letter), i=i, j=j, letter=letter))
额外注意
你贴的moused_clicked如果是类的实例方法,第一个参数必须是self,否则会出现参数数量不匹配的报错,需要调整定义:
def moused_clicked(self, e, coordinate, letter): print(coordinate) print(letter)
内容的提问来源于stack exchange,提问作者Naveh Mevorach
相关产品推荐
相关产品推荐

