Python遍历数组创建标签时,如何为每个元素绑定唯一事件处理器
问题原因
这是Python闭包的延迟绑定特性导致的:循环里定义的函数(包括lambda和内部的left_mouse)并不会立刻捕获当前的a值,而是在函数实际被调用(点击标签时)才去读取a的当前指向。循环结束后,a已经指向列表最后一个元素app3,所以所有标签的点击事件都会传入app3。
解决方案
下面三种方法都能解决这个问题,选你习惯的就行:
方法一:用lambda默认参数捕获当前值
给lambda添加一个默认参数,把当前循环的a赋值给它。默认参数会在定义lambda时就绑定当前的a值,而不是等到调用时再读取:
appLabels = [] for a in apps: lbl = ptg.Label(a.name) # 用app=a绑定当前循环的a实例 lbl.on_left_click = lambda _, app=a: showEditForm(app) appLabels.append(lbl)
方法二:用工厂函数创建独立闭包
写一个专门生成点击处理器的函数,每次调用时传入当前的a,让每个处理器都持有自己的a副本:
appLabels = [] def create_click_handler(app): def handler(_): showEditForm(app) return handler for a in apps: lbl = ptg.Label(a.name) lbl.on_left_click = create_click_handler(a) appLabels.append(lbl)
方法三:用functools.partial绑定参数
借助functools.partial把showEditForm和当前的a预先绑定,生成一个新的函数:
from functools import partial appLabels = [] for a in apps: lbl = ptg.Label(a.name) lbl.on_left_click = partial(showEditForm, a) appLabels.append(lbl)
内容的提问来源于stack exchange,提问作者Bobson Tobson
相关产品推荐
相关产品推荐

