Warum hier "lambda"?

Fragen zu Tkinter.
Antworten
DRW
User
Beiträge: 10
Registriert: Freitag 5. März 2021, 04:46

Tach zusammen,

beim nun zweiten Beitrag möchte ich doch kurz ohne förmliche Vorstell-Mail was zu mir sagen.
Einige Jahre programmiere ich schon (wenn ich "Turbo Pascal 3.0" sage, ahnen einige bestimmt, wie lange ;-) ) auch und hauptsächlich beruflich.
Daher kann ich Handbücher lesen und umsetzen und weiß auch bei OOP, was ich tue.
C++, VB/VBA, C#, SQL sind durchaus täglich Brot.

Python mit allem Zubehör ist mir aber komplett neu. Auslöser war Verarbeitung großer Datenmengen und Lineare Optimierung, wozu ich in VBA keine Lust hatte ;-) .

Einiges kann man/ich also ableiten, aber dann kommt sowas:

Code: Alles auswählen

[code]
def forget(widget): 
    widget.forget() 
  
def retrieve(widget): 
    widget.pack()
  
b1 = Button(root, text = "Btn 1") 
b1.pack() 

b2 = Button(root, text = "Btn 2", command = lambda : forget(b1))
b2.pack()

b3 = Button(root, text = "Btn 3", command = lambda : retrieve(b1)) 
b3.pack()#fill = BOTH, expand = True) 
[/code]

Was "lambda" soll und macht, meinte ich verstanden zu haben, aber das ließ mich stutzen...
Warum funktioniert das Ganze nicht ohne lambda??? Dazu finde ich keine Erklärung, habe es aber gerade am eigenen Leibe erlebt.

__init__ erstellt ein Textfeld und einen Button. In das Textfeld soll der Text, nach dem durch drücken von Button gesucht wird.
Logischerweise hat der Button eine Funktion zugewiesen bekommen.

Code: Alles auswählen

[code]
(  __init__ )
        self.enttxtSearch = CWidLblEntry(lblfrmtbl_b_search, "Filter / Suchen :",'', 12, 50)
        self.enttxtSearch.pack(side=tk.LEFT, padx=5)
        btnSearch = tk.Button(lblfrmtbl_b_search, text="Anwenden!", command=lambda: self.cmdbtnSearch(displtblname))
        btnSearch.pack(side=tk.LEFT, padx=6)

    def cmdbtnSearch(self,displtblname):
        ltxtSearch=self.enttxtSearch.get()
        print("s " ,ltxtSearch)
[/code]

CWidLblEntry ist ein eigenes Widget, das Label und Entry kombiniert.
Das "self" bei enttxtSearch gibt es, weil sonst das .get() nicht funktioniert.
Mein Vorgehen hier ist sicher nicht der Weisheit letzter Schluss - ich hasse globale Variablen, auch wenn "global" sich hier nur auf innerhalb der Klasse bezieht.
Auch hier bin ich für Gegenvorschläge dankbar.

Die Hauptfrage aber wieder in den Mittelpunkt gestellt:
Ohne "lambda" im "command =" denkt das Programm nicht daran, mir für ltxtsearch etwas auszugeben - mit funktioniert es.
Da ich kein Fan der vier Buchstaben "isso" bin, interessiert mich hier die Erklärung; gerne mit Quelle - ich habe nichts gefunden.

Grüße und schönen Sonntach!
Dirk
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

Zuerst einmal: Vokale kosten nichts. displtblname? Warum nicht display_table_name? Benutze keine kryptischen Abkürzungen, Code sollte gut lesbar sein und kein Buchsrabenrätsel.
Genauso CWidLblEntry. Das soll wohl irgendein LabelEntry sein. Das C ist überflüssig, weil der Leser an der Großschreibung erkennt, dass es sich um eine Klasse handelt. Wenn im Namen Label oder Entry vorkommt, ist das irgend ein GUI-Element, das Wid liefert also auch keinen Mehrwert.
Nach Konvention werden alle Variablen, Attribute und Methoden komplett klein geschrieben.
Zu lambda: command erwartet eine Funktion ohne Argumente, du hast aber eine Funktion mit Argumente, also besuchst du irgend etwas das die Argumente vorbelegt. Ohne Lambda hast du einen normalen Funktionsaufruf und der Rückgabewert wird als command-Argument benutzt. Statt lambda benutzt man in deinen Fällen aber functools.partial.
Klassen sind dazu da, gemeinsame Eigenschaften zu bündeln, das hast nichts mit globalen Variablen zu tun, und ist bei GUIs der übliche Weg um hunderte Argumente bei Funktionsaufrufen zu vermeiden.
DRW
User
Beiträge: 10
Registriert: Freitag 5. März 2021, 04:46

Tach Sirius3,

danke für Deine letztlich zum Ende hin hilfreiche Antwort.
Zuerst einmal (fast) OT:
Im Laufe des (Programmierer-)Lebens haben sich so manche Dinge festgesetzt, die die Namensgebung betreffen.
Jeder schwört hier auf sein eigenes Rezept und für jede Programmiersprache auf dieser Welt sitzt irgendwo einer, der sagt "nur so ist die Benennung richtig".
Das ist KEINERLEI Kritik gegen Deine Kritik an mir ;-) , sondern einfach nur eine Feststellung.

Was Dir verkorkst, sogar falsch und unnötig erscheint, hat für mich den Vorteil, über die Jahre in allen Programmiersprachen relativ gleich behandelt worden zu sein.
Wenn ich heute einen uuuuuralten Turbo-Pascal-Quelltext von mir ansehe, weiß ich meist immer noch auf Anhieb, was ich gemeint habe(n könnte).
Das heißt nicht, daß sich die Ansichten nie geändert hätten und natürlich auch Anpassungen stattfinden. Aber wenn in VBA alle Funktionen, die irgendwas holen mit "fget_" anfangen und die, die irgendwo was setzen mit "fset_", dann muss doch erstmal nur genau einer glücklich sein: Ich. Das andere Leute "das" "so" nie tun würden, ist mir - mit Verlaub - Wurscht.
Eins gibt es noch: Meine Kollegen müssen den Kunden weiterbetreuen können, auch wenn mir der berühmte "Blumentopf" auf den Kopf gefallen ist.
Das klappt seit 25 Jahren (ja, man kann auch 25 Jahre lang etwas falsch machen), und deswegen werde ich das nun in einer "neuen" Programmiersprache nicht mehr *wesentlich* ändern.
Soll heißen - Zitat - : "Nach Konvention werden alle Variablen, Attribute und Methoden komplett klein geschrieben."
steht in beliebigen Handbüchern für beliebige Programmiersprachen komplett anders (und wird von Anderen gaaaanz anders gesehen - nur ungarische Notation hat eine Existenberechtigung! [die finde ich z.B. wenigstens teilweise grausam....]). Und dabei möchte ich es eigentlich belassen.

Zum spannenden Teil:
"command erwartet eine Funktion ohne Argumente, du hast aber eine Funktion mit Argumente"
Das ist doch mal was, was ich mit meinem Diplomingenieur-Spatzenhirn begreife! (/* Rhetorik on: Warum steht das nirgends, außer in Deiner Antwort? Rhetorik off

"Statt lambda benutzt man in deinen Fällen aber functools.partial"
Da muß ich nochmal mit der Ente (duckduck.go) reden oder bei Dir darauf zurückkommen...

"Klassen sind dazu da, gemeinsame Eigenschaften zu bündeln, das hast nichts mit globalen Variablen zu tun..."
Danke, ist das also in Ordnung.
(Aber ob ich die Funktionsargumente ständig wiederhole oder "self." auf eine eigene Automatik-Taste lege, ist dann auch fast egal...)
DRW
User
Beiträge: 10
Registriert: Freitag 5. März 2021, 04:46

...den "Gruß, Dirk" hat er verschluckt - 'tschuldigung.
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

Natürlich ist gibt es in anderen Programmiersprachen andere Konventionen. In Spanisch werden Fragen mit ¿ eingeleitet um im Deutschen schreibt man Substantive groß.
Und die Rechtschreibregeln für Python sind hier festgelegt: https://www.python.org/dev/peps/pep-0008/
Ziel ist es, dass man eben dem Code nicht gleich ansieht, wer ihn geschrieben hat.
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@DRW: Deine Sichtweise kann ich nachvollziehen. Dennoch ist es von Vorteil, sich bei einer Programmiersprache an die Konventionen genau *dieser* Programmiersprache zu halten.

Zudem ist es bei einer dynamisch typisierten Sprache weiter von Vorteil, wenn sich an den Bezeichnern erkennen lässt, worum es sich handelt (aber nicht um welchen Typ es sich handelt, also genau *keine* ungarische Notation!) oder was eine Funktion "tut". Insbesondere andere, die den Code lesen und verstehen müssen, danken es einem.

Wenn man sich darauf einmal einlässt, will man dies nicht mehr missen. Sicherlich geht damit auch ein Gewöhnungseffekt einher. Das ist ähnlich, wie sich bei Taschenrechnern auf UPN einzulassen ... ;)
Benutzeravatar
__blackjack__
User
Beiträge: 12984
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@DRW: Zur Namensgebung: Nicht jeder schwört auf seins. Leute die das tun sind keine guten Programmierer. Man hält sich an die Konventionen der jeweiligen Programmiersprache und/oder dem Projekt. Diese Konventionen gehören dazu, denn sie vermitteln Informationen. Es gibt immer weniger Drittanbieter die sich *nicht* an Style Guide for Python Code halten.

Und ganz allgemein sind solche Unfälle wie `CWidLblEntry` oder Vokale weglassen grundsätzlich objektiv schlecht. Das hat nichts mit Meinung oder persönlichem Stil zu tun, das ist einfach messbar schlechter lesbar.

Das kann Dir wurscht sein, Du wirst es hier aber in jeder Antwort wieder hören wenn Du Code mit komischen Namen zeigst.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
bb1898
User
Beiträge: 199
Registriert: Mittwoch 12. Juli 2006, 14:28

Kleine Ergänzung: Das Modul functools mit allen seinen Funktionen, hier insbesondere "partial", ist in der offiziellen Dokumentation erklärt, zuständig ist der Teil "The Python Standard Library" und darin "Functional Programming Modules". Auf der Startseite der Dokumentation ist das die "Library Reference" (wieso die unter dem Kopfkissen liegen bleiben soll, erschließt sich mir nicht - bei mir hat sie ihren Stammplatz auf dem Bildschirm, offen).
Antworten