Die freien Namen im ``lambda``-Ausdruck werden erst beim Aufruf ausgewertet, dass heisst erst beim Aufruf wird geschaut an was die Namen `self` und `t` in diesem Augenblick gebunden sind. `self` bleibt ja immer gleich, nur `t` wird in der Schleife immer an verschiedene Texte gebunden und wenn die `command`-Funktion aufgerufen wird, ist das `t` an das letzte Element vom Schleifendurchlauf gebunden.
Default-Argumente von Funktionen werden dagegen immer bei der Definition an die Namen gebunden.
Probleme mit Variablen und tkinter
Danke BlackJack !!!
So nun habe ich mir gedacht auch die Tasten (+,-,etc) wiederholen sich in ihrer Funktion und so müsste es wieder mit lambda funktionieren. Nur geht es nicht - liegt es am syntax oder ist es ein denkfehler ?
gruss und dank frank
So nun habe ich mir gedacht auch die Tasten (+,-,etc) wiederholen sich in ihrer Funktion und so müsste es wieder mit lambda funktionieren. Nur geht es nicht - liegt es am syntax oder ist es ein denkfehler ?
Code: Alles auswählen
# -*- coding: iso-8859-15 -*-
from Tkinter import *
class Rechner (Frame):
def __init__(self, master=None):
tastenlayout = [("7",3,7,1,10,0),("8",3,7,2,0,0),("9",3,7,3,10,0),("4",3,8,1,0,10),
("5",3,8,2,0,0),("6",3,8,3,0,0),("1",3,9,1,0,0),("2",3,9,2,0,0),
("3",3,9,3,0,0),("0",3,10,1,0,10),(",",3,10,3,0,0)]
funktastlayout = [("/",3,7,4,0,0),("X",3,8,4,0,0,),("-",3,9,4,0,0),("+",3,10,4,0,0)]
speicher=""
Frame.__init__(self, master,)
self.pack()
for text, width, row, column, padx, pady in tastenlayout:
self.tasten = Button(self, text=text,width=width, command=lambda t=text: self.ausgabe.insert(50,t))
self.tasten.grid(row=row, column=column, padx=padx, pady=pady)
for text, width, row, column, padx, pady in funktastlayout:
self.funktasten = Button(self, text=text,width=width, command=lambda speicher=speicher+self.ausgabe.get()+ text : self.ausgabe.delete(0,END))
self.funktasten.grid(row=row, column=column, padx=padx, pady=pady)
self.ausgabe = Entry(self,width=29,justify="right",)
self.ausgabe.grid(row=0, column=0,columnspan=6,pady=10)
root = Tk()
root.title('mudda`s Rechner 1.0')
root.config(cursor='crosshair')
Rechner(root).mainloop()
Wie schon gesagt werden die Default-Argumente ausgewertet wenn die Funktion definiert wird. Also das was Du dort an `speicher` bindest, wird in der Schleife schon ausgewertet. Davon abgesehen das `self.ausgabe` zu dem Zeitpunkt noch nicht existiert, dürfte das nicht der richtige Zeitpunkt sein.
Da ``lambda``-Ausdrücke auf einfache Ausdrücke beschränkt sind, musst Du hier mit einem sogenannten "Closure" arbeiten. Ungetestet:
Da ``lambda``-Ausdrücke auf einfache Ausdrücke beschränkt sind, musst Du hier mit einem sogenannten "Closure" arbeiten. Ungetestet:
Code: Alles auswählen
def _make_operator_command(self, text):
def operator_command():
self.speicher += self.ausgabe.get() + text
self.ausgabe.delete(0, END)
return operator_command
Danke !!!
Also für Doofe: Mein Programm "hängt" beim der Ausführung in den beiden Schleifen und beim Tastendruck beginnt die "Auswertung" ....?! Da self.ausgabe.get () erst nach dem Drücken der Taste bekannt ist, kann ich es auswerten ?! Vorhergehend habe ich es mit def eingabeminus(self) ausgewertet und somit war self.ausgabe.get() bekannt ?! Dein Tip ist ja sowas in der Art nur nicht für alle einzeln, sondern für +,- etc. in einem Vorgang ? - alles klar ? Der Befehl return wird innerhalb eines Körpers einer Funktion verwendet -- habe ich abgeschrieben... Ich rufe beim Drücken der Tasten die Funktion def operator_command auf und diese gibt mir die werte in die Schleife zurück ...?. Bei dem vorhergenden Programm habe ich das nicht gemacht - ging aber doch auch ?
gruss und dank frank
Also für Doofe: Mein Programm "hängt" beim der Ausführung in den beiden Schleifen und beim Tastendruck beginnt die "Auswertung" ....?! Da self.ausgabe.get () erst nach dem Drücken der Taste bekannt ist, kann ich es auswerten ?! Vorhergehend habe ich es mit def eingabeminus(self) ausgewertet und somit war self.ausgabe.get() bekannt ?! Dein Tip ist ja sowas in der Art nur nicht für alle einzeln, sondern für +,- etc. in einem Vorgang ? - alles klar ? Der Befehl return wird innerhalb eines Körpers einer Funktion verwendet -- habe ich abgeschrieben... Ich rufe beim Drücken der Tasten die Funktion def operator_command auf und diese gibt mir die werte in die Schleife zurück ...?. Bei dem vorhergenden Programm habe ich das nicht gemacht - ging aber doch auch ?
gruss und dank frank
Ehrlich gesagt habe ich Deinen letzten Text nicht verstanden. 
Das `command`-Argument von `Button` will eine aufrufbare Funktion/Methode haben. Die Methode `_make_operator_command()` hat als Rückgabewert eine Funktion, nämlich eine Instanz von der inneren Funktion `operator_command()`. Diese kann man an das `command`-Argument eines Buttons binden. Die Funktion wird genau dann aufgerufen wenn man auf den Button klickt.
Innere Funktionen haben Zugriff auf die lokalen Namen des Aufrufs der umgebenen Funktion, dass heisst wenn man so einen Namen benutzt, bekommt man das Objekt an den der äussere Name gerade gebunden ist. Wenn man eine Instanz der inneren Funktion als Rückgabewert benutzt, nimmt diese den lokalen Namensraum des äusseren Aufrufs sozusagen mit.

Das `command`-Argument von `Button` will eine aufrufbare Funktion/Methode haben. Die Methode `_make_operator_command()` hat als Rückgabewert eine Funktion, nämlich eine Instanz von der inneren Funktion `operator_command()`. Diese kann man an das `command`-Argument eines Buttons binden. Die Funktion wird genau dann aufgerufen wenn man auf den Button klickt.
Innere Funktionen haben Zugriff auf die lokalen Namen des Aufrufs der umgebenen Funktion, dass heisst wenn man so einen Namen benutzt, bekommt man das Objekt an den der äussere Name gerade gebunden ist. Wenn man eine Instanz der inneren Funktion als Rückgabewert benutzt, nimmt diese den lokalen Namensraum des äusseren Aufrufs sozusagen mit.
Das geht mir bei Deinen Erklärungen auch so (soll nicht wertend sein, sondern mir fehlen die Fachbegriffe oder das nötige Hintergrundwissen) Ich komme aus der Sonderpädagogik, deswegen lerne ich immer über das Handeln z.B.: Man lernt das Autofahren indem man ein Auto fährt und nicht weil man es in der Theorie kann. Immer beides zusammen, deswegen auch meine "doofen" Fragen. In dem Wort begreifen steckt das Wort greifen. Erst mit dem Greifen nach etwas kann man es begreifen - hört sich gut an - blöde Pädagogen
.
Trotzdem vielen Dank für Deine schnellen Antworten und ich versuche es weiter mal mit Lesen.
gruss und dank frank

Trotzdem vielen Dank für Deine schnellen Antworten und ich versuche es weiter mal mit Lesen.
gruss und dank frank
Stichwort: Closures
Ein par Beispiel zum letzen Post von BlackJack gibt es hier: [wiki]Closures richtig anwenden[/wiki]
Und eine ausführlich Erklärung hier: http://de.wikipedia.org/wiki/Closure
Ein par Beispiel zum letzen Post von BlackJack gibt es hier: [wiki]Closures richtig anwenden[/wiki]
Und eine ausführlich Erklärung hier: http://de.wikipedia.org/wiki/Closure
@kaytec: "Closures" sind auch ein klein wenig komplizierter. Aber wenn man sie erst einmal verstanden hat, dann lassen sie sich vor allem in der GUI-Programmierung verwenden um Callback-Funktionen zu erstellen, die komplexere Dinge anstellen können, als mit ``lambda`` möglich ist.
Zum Thema ausprobieren: Dazu eignet sich Python durch den interaktiven Interpretierer sehr gut. Man kann "live" mit den ganzen Objekten herumspielen. Ein weiteres beliebtes "Closure"-Beispiel ist eine Funktion, die Funktionen produziert, welche einen festen Wert zu einem Argument addieren:
Zum Thema ausprobieren: Dazu eignet sich Python durch den interaktiven Interpretierer sehr gut. Man kann "live" mit den ganzen Objekten herumspielen. Ein weiteres beliebtes "Closure"-Beispiel ist eine Funktion, die Funktionen produziert, welche einen festen Wert zu einem Argument addieren:
Code: Alles auswählen
In [46]: def make_adder(number):
....: def add(n):
....: return number + n
....: return add
....:
In [47]: add5 = make_adder(5)
In [48]: add5(0)
Out[48]: 5
In [49]: add5(10)
Out[49]: 15
In [50]: add5(42)
Out[50]: 47
hi,
hier mal dein Code wie es ein bisschen optimiert funktionieren könnte.
Dabei kannst auch gleich die unschlagbaren kombination von Tkinters layout Manager sehen.
link: http://paste.pocoo.org/show/1159/
Gruss
pyStyler
hier mal dein Code wie es ein bisschen optimiert funktionieren könnte.
Dabei kannst auch gleich die unschlagbaren kombination von Tkinters layout Manager sehen.
link: http://paste.pocoo.org/show/1159/
Gruss
pyStyler
Hallo pystyler !!
Ja so einen gibt es schon im Forum, doch bei meinem wollte ich nicht, dass die Zeichen +,- etc. im Rechenvorgang zusehen sind, sondern es wie ein richtiger taschenrechener funktioniert.
gruss und dank frank
Ja so einen gibt es schon im Forum, doch bei meinem wollte ich nicht, dass die Zeichen +,- etc. im Rechenvorgang zusehen sind, sondern es wie ein richtiger taschenrechener funktioniert.
gruss und dank frank
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Mein "richtiger Taschenrechner" Zeigt auch Rechenzeichen an - finde ich sehr praktisch, weil ich die Eingaben editieren kann.kaytec hat geschrieben:doch bei meinem wollte ich nicht, dass die Zeichen +,- etc. im Rechenvorgang zusehen sind, sondern es wie ein richtiger taschenrechener funktioniert.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Hallo pystyler !!
Da hast Du recht - habe ja auch ihn gefunden bei meiner Suche nach einem Anstoss, doch ihn kopieren wäre ja nicht gerade eine Anforderung - code zu klauen ist ok, doch wollte ich es halt anders machen und dabei lernen. Es geht nicht um besser oder schlechter, sondern um den Spass an der Sache (intrinsiche Motivation).
Danke für Deine Links - gruss frank
Da hast Du recht - habe ja auch ihn gefunden bei meiner Suche nach einem Anstoss, doch ihn kopieren wäre ja nicht gerade eine Anforderung - code zu klauen ist ok, doch wollte ich es halt anders machen und dabei lernen. Es geht nicht um besser oder schlechter, sondern um den Spass an der Sache (intrinsiche Motivation).
Danke für Deine Links - gruss frank
So - habe es mal eingebaut! Es passiert nicht´s - bekomme aber auch keine Fehlermeldung. Das Entry - Feld wird auch nicht gelöscht ??
gruss und dank frank
Code: Alles auswählen
self.funktasten = Button(self, text=text,width=width, command=lambda text=text:self._make_operator_command)
self.funktasten.grid(row=row, column=column, padx=padx, pady=pady)
self.ausgabe = Entry(self,width=29,justify="right",)
self.ausgabe.grid(row=0, column=0,columnspan=6,pady=10)
def _make_operator_command(self, text):
def operator_command():
self.speicher += self.ausgabe.get() + text
self.ausgabe.delete(0, END)
return operator_command
gruss und dank frank
Erst einmal brauchst Du natürlich das ``lambda`` nicht mehr. Die Funktion soll ja von der neuen Methode erzeugt werden. Und dazu musst Du die auch aufrufen ─ mit dem Text der eingefügt werden soll als Argument.
Der Name `taste` braucht auch nicht an das `Rechner`-Objekt gebunden werden. Ausserdem ist Mehrzahl falsch, der Name ist ja immer nur an *einen* `Button` gebunden. In der Zifferntasten-Schleife ist es das gleiche.
Code: Alles auswählen
taste = Button(..., command=self._make_operator_command(text))
So an den Rest habe ich auch mal versucht einzubauen, doch macht das so Sinn oder geht es noch einfacher ?
gruss und dank frank
Code: Alles auswählen
def make_auswertung(self,text):
def auswerten():
if text =="C":
self.ausgabe.delete(0,END)
self.speicher = ""
self.mspeicher = ""
if text =="%":
self.speicher = self.ausgabe.get()
self.speicher = (self.speicher + "/" + "100" + "*")
self.ausgabe.delete(0,END)
if text =="M":
if self.ausgabe.get() =="":
self.speicher = self.speicher + self.mspeicher
if self.ausgabe.get() !="":
self.mspeicher = self.ausgabe.get()
self.ausgabe.delete(0,END)
self.ausgabe.insert(50,"")
if text =="+/-":
self.vorzeichen = str(float (self.ausgabe.get()) * -1)
self.ausgabe.delete(0,END)
self.ausgabe.insert(50,self.vorzeichen)
if text =="=":
try:
self.speicher = str(eval (self.speicher + self.ausgabe.get()))
self.ausgabe.delete(0,END)
self.ausgabe.insert(50,self.speicher)
self.speicher = ""
except:
self.ausgabe.delete(0,END)
self.speicher = ""
self.ausgabe.insert(50,"E")
return auswerten
Das "verstecken" der Alternativen in einer inneren Funktion und die ganzen ``if``-Abfragen finde ich persönlich unschön. Eine Funktion sollte möglichst nur eine abgegrenzte Funktionalität implementieren. `auswerten()` macht dagegen eine ganze Menge verschiedener Dinge.
So würde ich das machen, ja. Wobei ich wohl auch den Taschenrechner, d.h. die Logik davon, von der GUI trennen würde. Damit man den Taschenrechner selbst, ohne GUI (automatisch) testen kann und eventuell auch die GUI austauschbar ist.
Danke BlackJack !!!
Mir wurde bei einem anderem Programm gesagt:
"Hi kaytec!
Auf den ersten Blick würde ich sagen, dein Programm ist nicht kompliziert, sondern eher etwas zu ausformuliert. Du könntest mit einigen Schleifen sicher recht viel code sparen, da tw. eigentlich immer das selbe machst und nur die Namen austauscht. Zudem kann ich dir für solche Sachen Tix.LabelEntry empfehlen, dann ist's noch kürzer. "
Jetzt habe ich dieses Programm mit schleifen verkürzt - oder habe ich das nicht richtig verstanden?
Das wichtigste ist doch das Auslesen des string mit eval(self.speicher). Der Rest ist doch eigentlich nur für die Eingaben über die Oberfläche und das richtige Einlesen in den string ? Meinst du damit die Trennung von Oberfläche und Berechnung ?
gruss frank
Mir wurde bei einem anderem Programm gesagt:
"Hi kaytec!
Auf den ersten Blick würde ich sagen, dein Programm ist nicht kompliziert, sondern eher etwas zu ausformuliert. Du könntest mit einigen Schleifen sicher recht viel code sparen, da tw. eigentlich immer das selbe machst und nur die Namen austauscht. Zudem kann ich dir für solche Sachen Tix.LabelEntry empfehlen, dann ist's noch kürzer. "
Jetzt habe ich dieses Programm mit schleifen verkürzt - oder habe ich das nicht richtig verstanden?
Das wichtigste ist doch das Auslesen des string mit eval(self.speicher). Der Rest ist doch eigentlich nur für die Eingaben über die Oberfläche und das richtige Einlesen in den string ? Meinst du damit die Trennung von Oberfläche und Berechnung ?
gruss frank