Подтвердить что ты не робот

Команда 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", что означает, что они используют ту же функцию с тем же параметром.

Как я могу это решить?

4b9b3361

Ответ 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)