Tkinter назначает команду кнопки в цикле с помощью лямбды

#python #tkinter #late-binding

#питон #tkinter

Вопрос:

Я пытаюсь создать несколько Button s (с for циклом), например:

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

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

Ответ №1:

Проблема в том, что ваша ламба находится в цикле for. Ваш лямбда-индекс использует name переменную, но name переменная каждый раз переназначается через цикл for. Таким образом, в конце концов, все кнопки получают последнее значение, которое name было присвоено в цикле for. Чтобы избежать этого, вы можете использовать параметры ключевых слов по умолчанию в выражении lamba, например так:

 user_button = Tkinter.Button(self.root,  text=name,  command=lambda name=name: self.a(name))  

Это привязывает текущее значение name переменной к name аргументу ключевого слова lamba каждый раз в цикле, производя желаемый эффект.

Комментарии:

1. Это не проблема tkinter, это проблема, касающаяся вложенности функций, замыканий и т. Д. Оно также существует в совершенно других контекстах. Тем не менее 1, так как в противном случае это точно описывает, что происходит.

2. @glglgl Вы на 100% правы. Не лучший выбор слов с моей стороны, пересмотрю.

3. Большое вам спасибо за этот ответ. Это спасло меня от еще нескольких часов поисков.

4. что делать, если мы хотим выполнить несколько функций? я. а и я. б

5. это сработало для меня, но я заметил много странных вещей, подобных этому, с лямбдой. Есть ли причина, по которой лямбда вообще нужна?