tkinter creando botones para argumentos de comando de paso de bucle

Estoy intentando crear botones en tkinter dentro de un ciclo for. Y con cada ciclo, pase el valor de conteo como un argumento en el valor de comando. Entonces, cuando se llama a la función desde el valor del comando, puedo decir qué botón se presionó y actuar en consecuencia. El problema es, digamos que len es 3, creará 3 botones con los títulos “Juego 1” hasta “Juego 3”, pero cuando se presiona cualquiera de los botones, el valor impreso es siempre 2, la última iteración. Entonces parece que los botones se están haciendo como entidades separadas, pero el valor de i en los argumentos del comando parece ser el mismo. Aquí está el código:

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) 

¿Hay alguna manera de obtener el valor actual de i, en cada iteración, para seguir con ese botón en particular?

Cambia tu lambda a lambda i=i: self.open_this(i) .

Esto puede parecer mágico, pero esto es lo que está sucediendo. Cuando utiliza esa lambda para definir su función, la llamada a open_this no obtiene el valor de la variable i en el momento de definir la función. En su lugar, realiza un cierre, que es una especie de nota para él mismo que dice: “Debería buscar cuál es el valor de la variable i en el momento en que me llaman “. Por supuesto, la función se llama después de que el ciclo ha terminado, por lo que en ese momento siempre será igual al último valor del ciclo.

El uso del truco i=i hace que su función almacene el valor actual de i en el momento en que se define su lambda, en lugar de esperar a buscar el valor de i más tarde.

Así es como funcionan los cierres en python. Me encontré con este problema una vez. Puede usar functools.partial para esto.

 for i in range(3): self.button.append(Button(self, text='Game '+str(i+1), command=partial(self.open_this, i)))