Seite 1 von 1
Erstellen von Events
Verfasst: Mittwoch 15. Juni 2022, 13:14
von woto
Hallo zusammen,
ich beschäftige mich seit ca. 2 Wochen mit Python und habe ein kleines Programm erstellt, welches nach dem MVC-Prinzip aufgebaut ist:
1. eine Model-Klasse
2. eine Controller-Klasse
3. eine View-Klasse
Dabei geht es um eine Rollladensteuerung.
Die Controller-Klasse beinhaltet eine Rollladen-Klasse. Sobald ein Rollladen-Objekt eine Aktion initiiert (z.B. runter fahren), soll die Rollladen-Klasse eine Methode in der Controller-Klasse aufrufen, um mitzuteilen, dass der Rollladen runter fährt. Die Controller-Klasse veranlasst dann, den Eintrag in eine Datenbank über die Model-Klasse.
Meine Frage ist, wie muss die Rollladen-Klasse aufgebaut sein, damit die Methode in der Controller-Klasse aufgerufen wird. Im Prinzip müsste ich doch in der Rollladen-Klasse die Adresse der Methode in der Controller-Klasse hinterlegen, damit ich darüber dann diese aufrufen kann, oder?
VG Woto
Re: Erstellen von Events
Verfasst: Mittwoch 15. Juni 2022, 14:19
von __deets__
Du kannst grundsaetzlich Abhaengigkeiten einfach im Konstruktor uebergeben, und dann einfach entsprechend Methoden aufrufen. Wobei mir hier bei dem konstruierten Beispiel voellig der Plan fehlt, was da wie genau zusammen spielen soll.
Re: Erstellen von Events
Verfasst: Mittwoch 15. Juni 2022, 14:51
von __blackjack__
@woto: „Adresse der Methode“ klingt nicht nach Python, denn dort gibt es keine Adressen. Von solchen maschinenspezifischen Details abstrahiert die Sprache. Ist ja schliesslich eine Hochsprache.
Funktionen und Methoden sind in Python auch Objekte, und ja, wenn man etwas lose koppeln möchte, dann kann man auch aufrufbare Objekte übergeben, über die ein Objekt dann andere Objekte über bestimmte Ereignisse informieren kann.
Ungetestet:
Code: Alles auswählen
from enum import Enum, auto
class RolladenState(Enum):
OBEN = auto()
UNTEN = auto()
class Rolladen:
def __init__(self, state_change_callback=lambda state: None):
self.state_change_callback = state_change_callback
self._state = RolladenState.OBEN
@property
def state(self):
return self._state
@state.setter
def state(self, value):
self._state = value
self.state_change_callback(self.state)
def hochfahren(self):
if self.state is RolladenState.UNTEN:
...
self.state = RolladenState.OBEN
def runterfahren(self):
if self.state is RolladenState.OBEN:
...
self.state = RolladenState.UNTEN
Re: Erstellen von Events
Verfasst: Mittwoch 15. Juni 2022, 19:47
von woto
Vielen Dank euch beiden,
das hilft mir wahrscheinlich schon weiter. Werde das morgen mal versuchen, umzusetzen.
Wenn ich dann nicht weiter komme, werde ich mal ein Beispiecode posten.
Schönen Abend noch.
VG Woto
Re: Erstellen von Events
Verfasst: Donnerstag 16. Juni 2022, 08:56
von woto
Ich habe nun den Code von __blackjack__ getestet. Das ist das, was ich gebraucht habe. Vielen Dank.
Hier mein Testcode:
Code: Alles auswählen
class Rolladen:
#def __init__(self, state_change_callback=lambda state: None):
def __init__(self, state_change_callback):
self.state_change_callback = state_change_callback
self._state = None
@property
def state(self):
return self._state
@state.setter
def state(self, value):
self._state = value
self.state_change_callback(self.state)
def hochfahren(self):
self.state = "Ist OBEN"
def runterfahren(self):
self.state = "Ist UNTEN"
###############################################################
def MessageEventFunc(message):
print (str(message))
test = Rolladen(MessageEventFunc)
test.state = "OBEN"
test.state = "UNTEN"
test.hochfahren()
Es wird nun ein Text geschrieben, wenn das Property state geändert wird oder die Methode hochfahren() bzw. runterfahren(). Das Objekt test ruft dann die Ausgabefunktion MessageEventFunc mit dem auszugebenden Text auf.
Ich habe den Konstruktor in der Klasse Rolladen geändert, da ich mit der Lambda-Funktionen noch nichts gemacht habe.
Was genau bedeutet der Zusatz mit der Lambda-Funktion?
VG Woto
Re: Erstellen von Events
Verfasst: Donnerstag 16. Juni 2022, 09:36
von Sirius3
Die lambda-Funktion ist ein default-Argument, dass der Rolladen auch ohne Callback funktioniert.
Viel schlimmer ist, daß Du das enum für den State weggeschmissen hast. Strings sind kein Ersatz für definierte Zustände.
Re: Erstellen von Events
Verfasst: Donnerstag 16. Juni 2022, 09:42
von __deets__
Nicht nur das es weggeschmissen wurde, dann ist der Zustand auch noch inkonsistent geworden. Mal "OBEN", mal "Ist OBEN". Die Folgefrage "warum funktioniert mein State-Vergleich nicht?" ist schon vorgezeichnet. Und genau das ist der Grund, da wenigstens vordefinierte Konstanten zu benutzen, oder eben ein Enum.
Re: Erstellen von Events
Verfasst: Donnerstag 16. Juni 2022, 09:51
von woto
Hallo,
ja, die Strings kommen nachher nicht zu tragen. Ich wollte nur das Prinzip verstanden haben.
Das die Lambda-Funktion dazu da ist, dass der Rollladen auch ohne Callback funktioniert, wusste ich nicht.
Das mache ich natürlich wieder rein. Danke.
VG Woto
Re: Erstellen von Events
Verfasst: Donnerstag 16. Juni 2022, 09:59
von __blackjack__
@woto: Also ich finde `MessageEventFunc()` am schlimmsten.

Das fängt mit dem Namen an, der sich nicht an die konventionelle Schreibweise hält. Und dann das `Func` — Funktionen erkennt man daran, dass der Name eine Tätigkeit beschreibt, nicht das da noch mal unnützerweise im Namen steht, dass es eine Funktion ist.
In der Funktion ist der `str()`-Aufruf überflüssig, weil `print()` schon in Zeichenketten umwandelt vor der Ausgabe. Wenn man das entfernt, dann ist `MessageEventFunc()` eigentlich nur ein anderer Name für `print()`. Das kann man einfacher haben: ``MessageEventFunc = print``. Oder eben gleich `print()` verwenden.
Gleich danach kommt, dass die ``if``\s verschwunden sind und damit der Name `state_change_callback` inhaltlich falsch geworden ist.
Und wenn ich mir die Beispielverwendung so anschaue, sollte man wohl den Setter für `state` wohl eher nicht öffentlich anbieten. Mein Fehler.
Code: Alles auswählen
#!/usr/bin/env python3
from enum import Enum, auto
class RolladenState(Enum):
OBEN = auto()
UNTEN = auto()
class Rolladen:
def __init__(self, state_change_callback=lambda state: None):
self.state_change_callback = state_change_callback
self._state = RolladenState.OBEN
@property
def state(self):
return self._state
def _set_state(self, value):
self._state = value
self.state_change_callback(self.state)
def hochfahren(self):
if self.state is RolladenState.UNTEN:
# ...
self._set_state(RolladenState.OBEN)
def runterfahren(self):
if self.state is RolladenState.OBEN:
# ...
self._set_state(RolladenState.UNTEN)
def main():
rolladen = Rolladen(print)
assert rolladen.state is RolladenState.OBEN, rolladen.state
rolladen.runterfahren()
rolladen.runterfahren() # Keine Ausgabe.
rolladen.hochfahren()
if __name__ == "__main__":
main()