For Schleife - Zuordnung zu einem command

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
lernePython
User
Beiträge: 18
Registriert: Freitag 3. Februar 2017, 20:01

Code: Alles auswählen

liste = [[frame1_steuerung, "eins"],
          [frame2_steuerung, "zwei"],
          [frame3_steuerung, "drei"],
          [fram4_steuerung, "vier"]     
          ]

for i in range (0, len(liste)):
    tk.Button(liste[i][0],
        text = "Ausgabe des {0}-Diagramms".format(liste[i][1]),
                           command = lambda:make_matplot(liste[i][1])).grid(row = 0, column =6, padx = 10)




Was ich nicht vestehe ist, dass die in der Schleife generierten Buttons, den korrekten Namen ("eins", "zwei"...) erhalten die Funktion make_matplot aber
nur mit dem übergebenen String "vier" ausgeführt wird.
Ich hätte als Fehler eher verstanden, dass die Buttons dann auch alle den Text "vier" erhalten. Verständlich? Ich freue mich über Eure Hilfe.
P.S. stört Euch bitte nicht an den Namen, die wurden nur zu Forums-Zwecken so benannt.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ein grosser Klassiker. lambdas bilden keinen Abschluss (closure) ueber die *Werte* die sie zum Zeitpunkt ihrer Erzeugung gesehen haben, sondern die *Namen*, die praesent sind. Wenn deren Werte sich aendern (wie bei dir), dann greifen sie auf die neuesten Werte zu.

Stattdessen musst du *neue* Namen in einem eigenen Abschluss erzeugen:

Code: Alles auswählen

#python3
lambdas = [lambda i=i: print(i) for i in range(10)]
list(map(lambda l: l(), lambdas))
BlackJack

@lernePython: Statt ``lambda`` würde ich hier `functools.partial()` verwenden und auch die Indirektion und die magischen Indexwerte loswerden:

Code: Alles auswählen

from functools import partial

# ...

for parent, text in liste:
    tk.Button(
        parent,
        text='Ausgabe des {0}-Diagramms'.format(text),
        command=partial(make_matplot, text),
    ).grid(row=0, column=6, padx=10)
lernePython
User
Beiträge: 18
Registriert: Freitag 3. Februar 2017, 20:01

ahh super. Und wenn ich der Methode mehrere Werte übergeben möchte, dann packe ich sie einfach - mit einem Komma getrennt - hinten dran...

Code: Alles auswählen


for parent, function, text in matplot_ausgabebutton:
    tk.Button(parent, text = "Ausgabe des {0}-Diagramms".format(text), command = partial(make_matplot, function, text),).grid(row = 0, column = 6, padx = 10)

Vielen Dank für die schnelle Hilfe
Antworten