tkinter создает кнопки для аргументов команды прохождения цикла
Я пытаюсь создать кнопки в tkinter в цикле for. И каждый цикл пропускает значение я count в качестве аргумента в значении команды. Поэтому, когда функция вызывается из значения команды, я могу сказать, какая кнопка была нажата и действовать соответствующим образом. Проблема в том, что, скажем, len - 3, она создаст 3 кнопки с названиями "Игра 1" через "Игру 3", но когда нажата любая из кнопок, напечатанное значение всегда равно 2, последней итерации. Таким образом, кажется, что кнопки создаются как отдельные объекты, но значение я в аргументах команды кажется одинаковым. Вот код:
def createGameURLs(self):
self.button = []
for i in range(3):
self.button.append(Button(self, text='Game '+str(i+1),command=lambda:self.open_this(i)))
self.button[i].grid(column=4, row=i+1, sticky=W)
def open_this(self, myNum):
print(myNum)
Есть ли способ получить текущее значение я на каждой итерации, чтобы придерживаться этой конкретной кнопки?
Ответы
Ответ 1
Измените свою лямбду на lambda i=i: self.open_this(i)
.
Это может показаться волшебным, но вот что происходит. Когда вы используете эту лямбда для определения своей функции, вызов open_this не получает значение переменной я во время определения функции. Вместо этого он делает закрытие, что похоже на примечание к себе: "Я должен искать, какое значение переменной я в момент, когда я называюсь". Конечно, функция вызывается после завершения цикла, поэтому в это время я всегда будет равен последнему значению из цикла.
Использование трюка i=i
заставляет вашу функцию сохранять текущее значение я во время определения лямбда, а не ждать, чтобы посмотреть значение я позже.
Ответ 2
Вот как работают замыкания на питоне. Однажды я столкнулся с этой проблемой.
Вы можете использовать functools.partial
для этого.
for i in range(3):
self.button.append(Button(self, text='Game '+str(i+1), command=partial(self.open_this, i)))