Frage zu lambda

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
Steffo
User
Beiträge: 45
Registriert: Sonntag 24. Mai 2009, 19:38

Hallo,
bin noch neu was Python angeht.
Ich versuche in der zweiten Zeile den Wert i der Variable numb zuzuweisen. Anschließend soll eine Funktion mit dem Parameter numb aufgerufen werden:

Code: Alles auswählen

for i in range(8):
        portButton = Tkinter.Button(self.frame, text="Port" + str(i), fg="black", command=lambda: numb = i; self.resetPort(numb))
        portButton.grid(row=4, column=i, sticky=Tkinter.W)
Leider erhalte ich folgende Fehlermeldung:
Expected:)
Undefined variable: numb
Was mache ich falsch?

Danke im Voraus!

L. G.
Steffo
BlackJack

@Steffo: Die Syntax von ``lambda`` sieht anders aus. Die Argumentliste kommt zwischen ``lambda`` und dem ``:`` und ein ``;`` kann in einem einfachen Ausdruck überhaupt nicht vorkommen.
Steffo
User
Beiträge: 45
Registriert: Sonntag 24. Mai 2009, 19:38

Das mit der Argumentliste ist mir schon klar. Das Problem hierbei ist, dass die lambda-Funktion erst nach der Schleifen-Iteration aufgerufen wird und mir der jeweilige aktuelle Wert von "i" nicht mehr zur Verfügung steht, weswegen ich "i" irgendwie zwischenspeichern muss.
Wenn ich beispielsweise folgendes schreibe, wird der letzte Wert, nämlich 7, gespeichert:

Code: Alles auswählen

command=lambda: self.resetPort(i)
L. G.
Steffo
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

functools.partial ist dein Freund:

Code: Alles auswählen

command=functools.partial(self.resetPort, i)
Das Leben ist wie ein Tennisball.
Steffo
User
Beiträge: 45
Registriert: Sonntag 24. Mai 2009, 19:38

EyDu hat geschrieben:functools.partial ist dein Freund:

Code: Alles auswählen

command=functools.partial(self.resetPort, i)
Nein, du bist mein Freund! :)
Danke!!! :D

L. G.
Steffo
BlackJack

@Steffo: Nochmal: Die Argumentliste kommt zwischen das ``lambda`` und den ``:``. Das binden von ``numb`` einfach weg zu lassen, löst natürlich das Problem nicht.

Oh, und falls das Absicht war, dass ``numb = i`` in den „Körper” der Lambda-Funktion sollte — das löst das Problem natürlich auch nicht, denn dann würde eben noch `numb` der Wert zugewiesen den `i` nach dem letzten Schleifendurchlauf hatte.

Und schlag mal `numb` im Englisch-Wörterbuch nach. Abkürzungen sollte man vermeiden. Die hier ist vollkommen willkürlich und verwirrt zusätzlich weil ein ”sinnvolles” Wort dabei heraus kommt. Und das alles nur um insgesamt vier Zeichen zu sparen.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

@BlackJack: Ich glaube, du hast die Intention von Steffos Code falsch verstanden. Zumindest, scheint functools.partial genau das zu machen, was er benötigt hat. Das ``numb=i`` war meiner Meinung nach nur ein verzweifelter Versuch (oder ein Andeutung für uns), dass der Wert von i irgendwie beim Funktionsaufruf verwendet werden soll. Dass ``lambda numb=i: func(numb)`` eine mögliche Alternative zu partila ist, ist Steffo wahrscheinlich nicht klar gewesen. Für uns sieht das ganze dann natürlich nach einem falschen Aufruf von lambda aus.
Das Leben ist wie ein Tennisball.
Steffo
User
Beiträge: 45
Registriert: Sonntag 24. Mai 2009, 19:38

Ey Du hast Recht! Danke! :D

L. G.
Steffo
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Der Vollstaendigkeit halber: Mit `lambda` geht das auch.

Code: Alles auswählen

...
portButton = Tkinter.Button(self.frame, text="Port" + str(i), fg="black", command=lambda number=i: self.resetPort(number))
....
Aber bitte `functools.partial` benutzen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

BlackJack hat geschrieben: Und schlag mal `numb` im Englisch-Wörterbuch nach.
Toll, jetzt habe ich nen Ohrwurm: "I become so numb..." :mrgreen:
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Steffo
User
Beiträge: 45
Registriert: Sonntag 24. Mai 2009, 19:38

cofi hat geschrieben:Der Vollstaendigkeit halber: Mit `lambda` geht das auch.
Hat schon "EyDu" gesagt. :)
Aber bitte `functools.partial` benutzen.
Wieso?

L. G.
Steffo
BlackJack

@Steffo: Weil es verständlicher ist. Wer nicht weiss was es macht, kann einfach `functools.partial()` in der Dokumentation nachschlagen. Warum das mit Default-Argumenten funktioniert ist nicht so offensichtlich und wenn man es nicht weiss, auch nicht so einfach in der Dokumentation zu finden, weil man dann ja gar nicht genau weiss *wonach* man eigentlich sucht.
Steffo
User
Beiträge: 45
Registriert: Sonntag 24. Mai 2009, 19:38

OK, das ist ein Argument. :)
Danke! :)

L. G.
Steffo
Antworten