Python:在循环中创建 Tkinter 按钮时,如何在 lambda 函数中传递不同的参数?



这是我目前的脚本:

import tkinter as tk
class Soundboard(tk.Frame):
def __init__(self, sounds, master=None):
super().__init__(master)
self.sounds = sounds
self.pack()    
self.create_button_loop()
def create_button_loop(self):
self.buttons = {}
for name, sound in self.sounds.items():
self.buttons[name] = tk.Button(self, text=name, command = lambda :play_sound(sound))
self.buttons[name].pack(side='top')    
#sound = 10

def play_sound(a_sound):
print(a_sound)

#MAIN SCRIPT
if __name__ == '__main__':
sounds = {'a':1, 'b':2, 'c':3}
board = Soundboard(sounds)

有一个类,Soundboard,一个函数,play_sound,以及底部的脚本部分。声音是一个具有模式的字典{name : sound}当前sound只是一个数字,函数play_sound只是打印调用它的内容。

我一直遇到的问题在于Soundboardcreate_button_loop方法。在循环中,对于每个name/sound组合,在字典self.buttons中创建一个按钮,其中name是按钮的文本,sound传递给play_sound(lambda 语句(。

我想发生的是在创建按钮时sound通过lambda语句传递的sound,而不是按下按钮时sound是什么,因此play_sound应该打印sound的原始值。实际发生的情况是,当sound稍后(通过循环的下一次迭代(被重新分配时,当按下按钮时play_sound播放sound的当前值。

在此示例中,创建了 3 个按钮,"a"、"b"和"c"。当按下"a"时,打印"3"(最近一次重新分配sound是在for循环的最后一次迭代中,因此name/sound=c/3而不是"1",就像创建按钮"a"时一样。

如何避免在 lambda 语句中传递的sound值在sound更改时更改?我更喜欢这样的迭代方法,而不是为每个{name:sound}组合编写不同的回调函数,但如果这是最好的方法,请告诉我。提前谢谢你!

使用functools.partial而不是 lambda。

from functools import partial
...
self.buttons[name] = tk.Button(self, text=name, command=partial(play_sound, sound))

最新更新