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

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)

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

4b9b3361

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