如何在 for 中生成 lambda 函数

How to generate lambda functions within for

信息

目标

我有一段代码,可以为我生成自定义菜单。现在我想在鼠标悬停在菜单中的单个按钮上时更改它们的颜色。

代码

for i in cmd:
   button = Button([..set some stuff here..])
   button.bind("<Enter>", lambda name: button.config(bg=hovercolor))
   button.bind("<Leave>", lambda name: button.config(bg=color))
   button.pack()

我的想法是将 ENTER 和 LEAVE 事件绑定到每个按钮。要让 lambda 函数工作,它需要一个名称(在本例中是名称,但我不关心名称)。

问题

如果鼠标悬停在我生成的菜单中的任何按钮上,最后一个按钮的颜色会改变。
我认为这是由 lambda 函数的名称引起的。每个按钮都会生成一个新的同名 lambda 函数,覆盖 python 环境中之前的 lambda 函数。

我正在搜索:

一种为 lambda 函数生成名称的方法

鼠标悬停在按钮上时更改颜色的另一种方法。

已解决

for i in cmd:
   button = Button([..set some stuff here..])
    button.bind("<Enter>", lambda name, button=button: button.config(bg=hovercolor))
    button.bind("<Leave>", lambda name, button=button: button.config(bg=color))
   button.pack()

发生这种情况的原因正如您所说,名称被覆盖并且 lambda 表达式全部 运行 在相同的变量上。

你可以做的是创建一个回调工厂,这样你就可以将名称传递给函数,函数将 return 调用的回调。

def create_callback(button, bg_color):
  lambda x: button.config(bg=bg_color)

button.bind("<Enter>", create_callback(button, hovercolor))

问题是 button 的绑定。您的 lambda 表达式没有定义它,因此需要在外部范围(循环)中找到一个闭包。由于每次循环时值都会改变,当 lambda 函数为 运行 时,button 变量指向您创建的最后一个按钮,而不是它在定义 lambda 函数时指向的按钮。

您可以通过将每个按钮对象保存为默认参数来解决此问题:

 button.bind("<Enter>", lambda name, button=button: button.config(bg=hovercolor))

button=button 参数使 button 成为 lambda 中的局部变量,因此更改外部定义无关紧要。无需关闭!