@unique24: Also diese Getter und Setter sahen ja schon so furchtbar „javaesque“ aus, und jetzt steckst Du auch noch jede Klasse in ein eigenes Modul. Das ist Python verdammt. Ein Modul ist dazu da um zusammengehörige Funktionen und Klassen zu bündeln. Wenn man jede Klasse in ein eigenes Modul steckt ist das so als würde man in Java jede Klasse noch mal einzeln in ein Package stecken. Das macht keinen Sinn.
Die `Demo`-Klasse verstärkt diesen Java-Eindruck auch noch mal, denn das ist ja überhaupt keine Klasse, sondern einfach nur Funktionen die sinnfrei in eine Klasse gesteckt wurden und die die globale Variable `Demo.lights` verwenden. Das `lights`-Objekt gehört nicht als Attribut auf die Klasse. Da gehören in aller Regel nur Konstanten hin.
Eine `__init__()` ist dazu da ein Objekt zu initialisieren so dass der Aufrufer das erstellte, initialisierte Objekt danach benutzten kann. Wenn die `__init__()` erst wieder zurück kehrt wenn im Grunde das gesamte Programm abgelaufen ist, dann stimmt was mit dem Entwurf nicht. Python ist nicht Java, man muss nicht alles zwanghaft in Klassen stopfen.
Zu der `Lights` hatte ich ja bereits gesagt das man keine nummerierten Namen verwendet. Das ist einfach eine Liste von `Light`-Objekten und es macht keinen Sinn die als solche noch mal in einem Objekt zu verpacken das sonst keinerlei Funktionalität hat.
Die `Enum`-Werte sind Konstanten und Konstanten werden per Konvention KOMPLETT_GROSS geschrieben. Die Werte der Werte sind auch komisch. Warum verwendest Du da die Zahlen 0, 1, und -1? Die Werte sind egal wenn man die nicht irgendwo tatsächlich verwendet. `Enum` ist kein Zahltyp wie in C oder C++!
Warum gibt `get_status()` etwas zurück was `*_state` heisst? Das sollte angeglichen werden.
Wenn es nicht auch einen nicht-aktuellen Wert für `current_state`, `current_value`, und `current_mode` gibt, dann ist das `current_*` überflüssig, denn das ist ja der Normalfall, dass Attribute den aktuellen Zustand eines Objekts bestimmen.
Bei `state` scheint mir der Getter überflüssig zu sein.
Bei den ``if``\s bezüglich dem Modus schliessen die sich ja gegenseitig aus, also ist ``elif`` angesagt. Beziehungsweise in `set_mode()` macht die Abfrage ja gar keinen Sinn, weil in jedem Fall das gleiche passiert.
Bei den `value_*`-Attributen ist die Reihenfolge so Yoda-mässig. Das ist ja nicht der ”Wert Automatik” sondern der ”Automatikwert”. Aber das sollte vielleicht sowieso eher ein Wörterbuch sein das Modus auf Schalterzustand abbildet. Dann fallen die ganzen ``if``\s bezüglich Modus in beiden Methoden zu jeweils nur einer einzigen Zeile zusammen.
Zwischenstand (in *einem* Modul):
Code: Alles auswählen
#!/usr/bin/env python3
from enum import auto as enum_value, Enum
class SwitchState(Enum):
OFF = enum_value()
ON = enum_value()
UNDEFINED = enum_value()
class Mode(Enum):
AUTOMATIC = enum_value()
MANUAL = enum_value()
OVERRIDE = enum_value()
class Light:
def __init__(self, name):
self.name = name
self.mode_to_switch_state = dict.fromkeys(Mode, SwitchState.UNDEFINED)
self.state = SwitchState.UNDEFINED
self._mode = Mode.MANUAL
@property
def mode(self):
return self._mode
@mode.setter
def mode(self, value):
self._mode = value
self.update_gpio()
def switch(self, state, mode):
self.mode_to_switch_state[mode] = state
self.update_gpio()
def update_gpio(self):
self.state = self.mode_to_switch_state[self.mode]
def main():
lights = [Light(f"LED {i + 1}") for i in range(3)]
light = lights[0]
print("LED 1:", light.state.name)
light.switch(SwitchState.ON, Mode.MANUAL)
print("LED 1:", light.state.name)
light.switch(SwitchState.OFF, Mode.AUTOMATIC)
print("LED 1:", light.state.name)
light.mode = Mode.AUTOMATIC
print("LED 1:", light.state.name)
if __name__ == "__main__":
main()