Python ttk循环生成按钮如何传递变量值而非变量引用?
问题原因
这是Python闭包的延迟绑定特性导致的:lambda表达式中引用的count变量不会在lambda定义阶段求值,只会在lambda被实际调用(点击按钮)时才读取count的当前值。循环执行完成后count已经变为最终的14,因此所有按钮触发时都会取到这个最终值。
此前的拷贝操作没有生效,是因为没有把值绑定到lambda的独立作用域中,外层作用域的变量还是会被后续循环迭代覆盖。
解决方案
方案1:给lambda添加默认参数(最简便)
Python函数的默认参数会在函数定义阶段完成求值,我们可以把当前迭代的count值(或者直接传你需要的coin对象)作为默认参数绑定到lambda上,即可捕获当前迭代的实时值:
# 原代码行 # command=lambda: self.toggle(self.dictionary[f'bt_{count}']) # 修改后写法1:绑定当前count值 command=lambda count=count: self.toggle(self.dictionary[f'bt_{count}']) # 修改后写法2:直接绑定当前coin对象,无需通过字典取值,更简洁 command=lambda curr_coin=coin: self.toggle(curr_coin)
方案2:使用functools.partial绑定参数
你也可以用functools.partial提前固定要传递的参数,它会在定义时就把当前迭代的值绑定好:
首先导入工具:
from functools import partial
修改command参数写法:
command=partial(self.toggle, self.dictionary[f'bt_{count}']) # 同样可以直接传coin对象 command=partial(self.toggle, coin)
两种方案都可以解决参数绑定错误的问题。如果else分支的按钮也需要绑定点击事件,用相同的方法处理即可。
内容的提问来源于stack exchange,提问作者whygod
相关产品推荐
相关产品推荐

