Команда Tkinter назначить кнопку в цикле с лямбдой
Я пытаюсь создать несколько кнопок (с a для), например:
def a(self, name):
print name
users = {"Test":"127.0.0.0", "Test2":"128.0.0.0"}
row = 1
for name in users:
user_button = Tkinter.Button(self.root,
text=name,
command=lambda: self.a(name))
user_button.grid(row = row, column = 0)
row+=1
а для каждого из них каждый получает свой собственный параметр (Test get Test и Test2, получающий Test2), но когда я нажимаю кнопки, они оба печатают "Test2", что означает, что они используют ту же функцию с тем же параметром.
Как я могу это решить?
Ответы
Ответ 1
Проблема заключается в вашей lamba в цикле for. Ваша лямбда использует переменную name
, но переменная name
получает переназначение каждый раз через цикл for. Таким образом, в конце, все кнопки получают последнее значение, которому name
был назначен в цикле for. Чтобы этого избежать, вы можете использовать параметры ключевого слова по умолчанию в своем выражении lamba следующим образом:
user_button = Tkinter.Button(self.root,
text=name,
command=lambda name=name: self.a(name))
Это привязывает текущее значение переменной name
к аргументу ключевого слова lamba name
каждый раз через цикл, создавая желаемый эффект.
Ответ 2
Как поясняется принятым ответом, все кнопки получают последнее значение, которое было присвоено " name
". Это потому, что это действительно значение переменной при выполнении функций.
Причина, по которой назначаются параметры по умолчанию, заключается в том, что параметры по умолчанию оцениваются при выполнении определения функции. Это означает, что выражение оценивается один раз, когда функция определена, и что для каждого вызова используется одно и то же "предварительно вычисленное" значение. Это справедливо для нормального функционального синтаксиса, а также для лямбда-функций.
Таким образом, поскольку " command=
" также является назначением по умолчанию, вышеуказанный код можно переписать следующим образом, в котором переменная "вызов" повторно используется для каждой функции, но отдельные функции будут оставаться прикрепленными к кнопкам:
for name in users:
call = lambda defaultname=name: self.a(defaultname))
user_button = Tkinter.Button(self.root, text=name, command=call)