Función Tkinter lambda

(Como indica la etiqueta 'tarea', esto es parte de un a lo grande proyecto de Ciencias de la Computación.)

Estoy escribiendo un ¡Peligro! simulación en Python con tkinter, y tengo un gran problema con el uso de la función lambda en los botones. Asumir root = Tk() and categories es una lista.

# Variable to keep the buttons
root._buttons = {}

# Display headers on top of page
for i in range(5):
    # Get category name for display in main window
    name = categories[i]
    b = Label(root, text=fill(name.upper(), 10), width=18, height=3,\
        bg="darkblue", fg="white", font=("Helvetica bold", "", 11))
    b.grid(row=0, column=i)

    # Create list of buttons in that variable (root._buttons)
    btnlist = [None]*5

    # Display individual questions
    for j in range(5):

        # Make a button for the question
        b = Button(root, text="$" + str(200 * (j+1)), width=8, height=1,
            bg="darkblue", fg="orange", font=("Impact", "", 30))
        b.cat = name
        b.value = 200 * (j + 1)
        b.sel = lambda: select(b.cat, b.value)

        # Add callback event to button
        print(b.cat, b.value, b.sel)
        b.config(command=b.sel)

        # Add button to window
        b.grid(row=j+1, column=i)

        # Append to list
        btnlist[j] = b

    root._buttons[categories[i]] = btnlist

Para todo el código, consulte mi pequeño Code Viewer (¡en construcción!)

Está en lambda: select(b.cat, b.value) donde parece ocurrir el problema, porque cuando hago clic en cualquier botón del tablero, siempre va al último botón del tablero. He probado otros enfoques, desafortunadamente todos usando lambda, y no he visto ningún enfoque que no involucre lambda.

preguntado el 12 de junio de 12 a las 22:06

¿Responde esto a tu pregunta? Python Lambda en un bucle -

2 Respuestas

Cambiar

lambda: select(b.cat, b.value)

a

lambda b = b: select(b.cat, b.value)

En tu código original, b no es una variable local del lambda; se encuentra en el ámbito de aplicación. Una vez el for-loop esta completado, b conserva su último valor. Es por eso que el lambda Todas las funciones utilizan el último botón.

Si define la lambda para que tome un argumento con un valor predeterminado, el valor predeterminado se determina (y fija) en el momento en que se activa la lambda. se define. Ahora b es una variable local de la lambda, y cuando se llama a la lambda sin argumentos, Python establece b al valor predeterminado que felizmente se establece en varios botones diferentes según se desee.

Respondido el 12 de junio de 12 a las 22:06

He estado atascado en este problema en particular durante 3 días. Incluso mi maestro no puede entenderlo. ¡¡Muchas gracias!! - Sammi de Guzmán

Le permitiría ser más expresivo si reemplazara la expresión lambda con una fábrica de funciones. (suponiendo que va a llamar a esto varias veces). De esa manera, puede realizar tareas, agregar lógica más complicada, etc. más adelante sin tener que lidiar con las limitaciones de lambda.

Por ejemplo:

def button_factory(b):
    def bsel():
        """ button associated with question"""
        return select(b.cat, b.value)
    return bsel

Dada una entrada b, button_factory devuelve una función invocable con () que devuelve exactamente lo que quieres. La única diferencia es que puedes hacer tareas, etc.

Aunque inicialmente puede ocupar más líneas de código, le brinda una mayor flexibilidad más adelante. (por ejemplo, podría adjuntar un contador a bsel y poder contar cuántas veces se seleccionó una pregunta en particular, etc.).

También ayuda a la introspección, ya que puede hacer que cada cadena de documentación identifique claramente con qué pregunta está asociada, etc.

Respondido el 12 de junio de 12 a las 23:06

Probé su solución y funciona bien, pero no estaba realmente dentro del alcance de mi curso, por lo que realmente no pude usarla. Sin embargo, probé la solución de @unutbu también usando lambda. ¡Gracias de cualquier manera! - Sammi de Guzmán

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.