Wischfunktion durch Buttonklick hervorrufen

Fragen zu Tkinter.
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: das was Du da so verteufelst, weil Du es nicht kennst, nennt sich closure und existiert so in fast jeder modernen Programmiersprache. So lange eine Funktion schön kurz ist, hilft es, umständliches Kopieren von Argumenten in Attribute, die man eigentlich nicht in einer Funktion neu einführen sollte, zu verhindern.
BlackJack

@Alfons Mittelmeyer: Das ist semantisch keine Klasse. Das ist nur formal Eine.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:@Alfons Mittelmeyer: Das ist semantisch keine Klasse. Das ist nur formal Eine.
Wieso ist das semantisch keine Klasse? Es ist natürlich eine Klasse. Nur macht so eine Klasse wenig Sinn, wenn man von dieser nur eine einzige Methode benützt. Dann kann man genauso gut eine Funktion nehmen.

Aber wenn man davon ausgeht, dass man das eh nur für einen SwipeFrame braucht, dann ist so ein SwipeFrame natürlich ein Klasse. Wenn man weiter davon ausgeht, dass diese Swipe Fenster alle gleich groß sind, dann kann man auch Größenangaben und Koordinatenangaben in diesen SwipeFrame verlagern.

Also SwipeFrame ist bestimmt eine Klasse:

Code: Alles auswählen

import tkinter as tk

# ---- Definition of SwipeFrame ---------------

class SwipeFrame(tk.Frame):
    def __init__(self,master, **kwargs):
        kwargs['width']=200
        kwargs['height']=150
        tk.Frame.__init__(self, master, **kwargs)
        self.ydown=300
        self.yup=150
        self.timestep=3
        self.place(y=self.ydown,x=0)

    def wish_on(self):
        self.wish(self.ydown,self.yup,-1,self.timestep)

    def wish_off(self):
        self.wish(self.yup,self.ydown,1,self.timestep)

    def wish(self,y0, yn, step,timestep):
        def do_move(y):
            y += step
            self.place(y=y)
            if y != yn:
                self.after(timestep, do_move,y)
        do_move(y0)
        
# ---- GUI ---------------------------------------
 
class Mainframe(tk.Frame):
    def __init__(self,master,**kwargs):
        tk.Frame.__init__(self,master,**kwargs)
        tk.Label(self, text='Screen',bg=self['bg']).place(y=0,x=0)
        tk.Button(self, text='wish on', command=self.wish_on).place(y=243,x=50)
        self.button_frame = ButtonFrame(self,bg='#d9d93c')

    def wish_on(self):
        self.button_frame.wish_on()
 
class ButtonFrame(SwipeFrame):
    def __init__(self, master, **kwargs):
        SwipeFrame.__init__(self, master, **kwargs)
        tk.Label(self, text='Swipe Window',bg=self['bg']).place(y=0,x=0)
        tk.Button(self, text='wish off',command=self.wish_off).place(y=93,x=50)
 
def main():
    app = tk.Tk()
    app.geometry("280x370")
    mainframe = Mainframe(app, width=200, bg='#d949d9', height=300)
    mainframe.place(y=28, x=43)
    app.mainloop()
   
if __name__ == '__main__':
    main()
asse:
BlackJack

@Alfons Mittelmeyer: Es ist semantisch keine Klasse. Die Begründung hast Du ja selbst schon geschrieben.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:@Alfons Mittelmeyer: Es ist semantisch keine Klasse. Die Begründung hast Du ja selbst schon geschrieben.
Die Klasse ist syntaktisch richtig. Auch semantisch stimmt sie. Nur pragmatisch ist diese Klasse nicht sinnvoll.

Syntaktisch richtig wäre etwa dieses Datum: 29. Februar 2017
Semantisch ist dieses Datum allerdings falsch.
Pragmatisch unklug wäre es, stets nur am 29. Februar jährlich fällige Zahlungen zu leisten.
BlackJack

@Alfons Mittelmeyer: Nein, das ist semantisch keine Klasse. Diese ”Klasse” nimmt keine Aufgabe wahr für die man Klassen verwendet. Darum kann man ja auch so einfach und ohne einen Verlust eine Funktion daraus machen.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:@Alfons Mittelmeyer: Nein, das ist semantisch keine Klasse.
Leere Behauptung
BlackJack hat geschrieben:Diese ”Klasse” nimmt keine Aufgabe wahr für die man Klassen verwendet.
Genau solche Aufgaben nimmt sie wahr. So hat man dadurch eine Datenkapselung und braucht keine globalen Variablen verwenden. Dann kann man mehrere Objekte der Klasse erzeugen, wenn etwa nicht hintereinander solche Wish Aktionen erfolgen sollen, sondern ziemlich gleichzeitig.
BlackJack hat geschrieben:Darum kann man ja auch so einfach und ohne einen Verlust eine Funktion daraus machen.
Für den Fall, dass man nicht mehrere Wish-Aktionen gleichzeitig durchführen will, sondern nur immer hintereinander, genügt eine Funktion. Ansonsten braucht man eine Klasse oder etwas, das auch die Eigenschaften einer Klasse besitzt. Für eine Klasse mit nur einer Methode kann man nämlich auch eine "closure" nehmen. Dass man in python eine Klasse mit nur einer Methode auch als closure realisieren kann, ist kein Grund, weshalb eine Klasse mit nur einer Methode keine Klasse sein soll.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:@Alfons Mittelmeyer: Es ist semantisch keine Klasse.
Die Syntax beschreibt die Regeln für richtige Sprachkonstrukte. Bei der Semantik geht es um die Beschreibung, wie der Interpreter den Code ausführen soll. Für Python gibt es allerdings keine systematische formale Beschreibung der Semantik sondern nur ein informelles Handbuch und eine Reihe von Implementationen.

Für ein Subset von Python namans minipy wurde allerdings eine formale Beschreibung der Semantik aufgestellt : Gideon Joachim Smeding - An executable operational semantics for Python
Quelle (PDF 91 Seiten): http://gideon.smdng.nl/wp-content/uploads/thesis.pdf

Darin heißt es etwa:
A class definition class x(e) : b creates a new class object. Its bases are set to the value of e, and the variables bound in b define its attributes.

Class definitions are not declarative, like in many other object oriented languages, but imperative in style. The body b and bases e of a new class are executed and evaluated when the class definition is executed.

Before the body is executed, the base objects have to be evaluated. The bases are represented by a tuple expression e.
When e has been evaluated, its result a is stored on the stack.

The body is executed with a new object c on top of the environment stack. All variable bindings within the body will be bound in the object c. Thus attributes of the new class are defined by ordinary variable bindings in the body.
Class definitions that are nested in class definitions, can not access the attributes of the class enclosing them through the environment. If the topmost environment g1 is an object, the body of the class definition is executed without g1 in the environment stack. Nested function definitions are limited in the same way
Vielleicht kapierst Du langsam, was Semantik einer Programmiersprache ist. Wenn ich selber einen Python Interpreter schreiben würde, der sich anders verhielte als in Python üblich, das würde eine Verletzung der Semantik sein.

Und solche Behauptungen wie eine Klasse mit nur einer Methode wäre semantisch keine Klasse, ist absoluter Unsinn. Die Semantik beschreibt, wie der Interpreter eine Klassendefinition abarbeiten soll.
BlackJack

@Alfons Mittelmeyer: Die Klasse nimmt die Aufgabe einer Klasse nicht wahr. Wo ist da Datenkapselung? Bei der Klasse über die ich hier rede hast Du einfach nur die Funktion als Methode in eine Klasse verschoben die `self` nicht benutzt und hast trotzdem behauptet das wäre semantisch eine Klasse. Ist es nicht.

Die Funktion die Du zur ”Methode” gemacht hast kann man auch für mehr als eine Animantion gleichzeitig verwenden, denn sie verwendet ja ein Closure ist aber selbst keins.

Semantik bezog sich auf OOP, nicht auf auf die semantik der Programmiersprache Python. Und objektorientiert gesehen ist eine Klasse die einfach nur eine Funktion als ”Methode” enthält semantisch keine Klasse. Das ist weder eine Unsinn noch ein leere Behauptung.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:@Alfons Mittelmeyer: Die Klasse nimmt die Aufgabe einer Klasse nicht wahr. Wo ist da Datenkapselung? Bei der Klasse über die ich hier rede hast Du einfach nur die Funktion als Methode in eine Klasse verschoben die `self` nicht benutzt und hast trotzdem behauptet das wäre semantisch eine Klasse. Ist es nicht.
Reden wir darüber?

Code: Alles auswählen

class WishClass():

    def wish(self,element,y0, yn, step,timestep):
        self.element = element
        self.yi = y0
        self.yn = yn
        self.step=step
        self.timestep = timestep
        self.do_move()
       
    def do_move(self):
        self.yi += self.step
        self.element.place(y=self.yi)
        if self.yi != self.yn:
            self.element.after(self.timestep, self.do_move)
Oder reden wir darüber?

Code: Alles auswählen

class WishClass():
    def wish(self,element,y0, yn, step,timestep):
        def do_move(y):
            y += step
            element.place(y=y)
            if y != yn:
                element.after(timestep, do_move, y)
        do_move(y0)
Vielleicht hatten wir aneinander vorbei geredet. Ich meinte den ersten Fall.

Im zweiten Fall ist natürlich eine Klasse nicht sinnvoll, da die Funktion darin durch die Closure auch bereits den Zweck erfüllt. Sinnvoll allerdings wird die Klasse wiederum, wenn wir sie durch weitere Methoden, etwa wish_on, wish_off und __init__ erweitern und auch noch von tk.Frame ableiten, wie ich das dann bei der Klasse SwipeFrame gemacht hatte.

Warum diskutieren wir über noch wenig ausgebaute Anfangszustände, ob die schon eine Klasse sind oder nicht, mit der Zeit wachsen sie sich schon noch aus.

Code: Alles auswählen

class SwipeFrame(tk.Frame):
    def __init__(self,master, **kwargs):
        kwargs['width']=200
        kwargs['height']=150
        tk.Frame.__init__(self, master, **kwargs)
        self.ydown=300
        self.yup=150
        self.timestep=3
        self.place(y=self.ydown,x=0)
 
    def wish_on(self):
        self.wish(self.ydown,self.yup,-1,self.timestep)
 
    def wish_off(self):
        self.wish(self.yup,self.ydown,1,self.timestep)
 
    def wish(self,y0, yn, step,timestep):
        def do_move(y):
            y += step
            self.place(y=y)
            if y != yn:
                self.after(timestep, do_move,y)
        do_move(y0)
Also eine sinnlose Diskussion, weil es am Ende dann doch eine Klasse ist.
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: am Anfang war die Klasse aber noch nicht sinnvoll. In Python ist es sehr einfach, aus einer Funktion eine Klasse zu machen, so dass es nicht nötig ist, alles auf Vorrat in eine Klasse zu packen.
Bei Deiner ersten Wunschklasse aus dem letzten Posting wäre es zudem sinnvoll, die Methode wish als __init__ zu schreiben und ihr noch eine start-Methode zu spendieren, weil, wie Du ja öfter schon betont hast, es ja sein kann, dass man mehrere Wünsche gleichzeitig erfüllt haben will, was ja nicht geht, wenn man nur ein WishClass-Exemplar hat, auf dem man mehrmals wish aufruft.
BlackJack

@Alfons Mittelmeyer: Ich rede von der Klasse bei der ich gesagt habe es wäre semantisch keine und Du behauptet hast es wäre doch eine, und das ist die Wo Du einfach nur die Funktion in eine formale Klasse verschoben hast. Ob sich solche Anfangszustände noch auswachsen oder nicht ist IMHO kein Grund für *den* Zwischenstand, da hätte man auch gleich den nächsten Schritt gehen können bei dem die Klasse einen Sinn hat. Der ist ja auch nicht wirklich weit weg.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Sirius3 hat geschrieben:@Alfons Mittelmeyer: Bei Deiner ersten Wunschklasse aus dem letzten Posting wäre es zudem sinnvoll, die Methode wish als __init__ zu schreiben
Ja, man kann auch wish als __init__ implementieren. Dann würde bei jedem Aufruf ein neues Wishobjekt instanziert werden. Das kann man tun, weil man nicht nicht so ungegeuer viel wisht, dass es den Garbage Collector sehr strapazieren würde. Wenn man allerdings jedem zu verschiebendem Frame ein eigenes Wishobjekt fest zuordnet, dann braucht sich der Garbage Collector nicht um das Aufräumen ständig neu erzeugter Wishobjekte kümmern. Aber das spielt sowieso keine Rolle.
Sirius3 hat geschrieben:und ihr noch eine start-Methode zu spendieren, weil, wie Du ja öfter schon betont hast, es ja sein kann, dass man mehrere Wünsche gleichzeitig erfüllt haben will, was ja nicht geht, wenn man nur ein WishClass-Exemplar hat, auf dem man mehrmals wish aufruft.
Nein, man hätte dann nicht nur ein einziges WishClass-Exemplar sondern jedes Wish-Fenster hätte dann sein eigenes Wish-Exemplar gehabt. Im Endeffekt ist es ja jetzt auch so, weil nämlich jetzt SwipeFrame und Wish-Exemplar identisch sind.
Antworten