UML in Python

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
magocode
User
Beiträge: 24
Registriert: Dienstag 9. Mai 2023, 08:53

Hallo wenn ich folgendes UML Diagramm habe und ich die Klasse Ausverkauft in Python darstellen will , ist dies richtig wie ChatGPT es vorgibt? Wenn es eine öffentliche static get Methode und einen private Konstruktor gibt dann handelt es sich um Singleton ?

UML:

Zustand {abstract}
--------------------------------
keine Attribute
--------------------------------
+auswertung(Konzert):void{abstract}


und eine Tochterklasse zu Zustand:

Ausverkauft
--------------------------------
-ausverkauft:Ausverkauft{static}
--------------------------------
-Ausverkauft()
+getAusverkauft():Ausverkauft{static}
+auswertung(Konzert):void

Code: Alles auswählen

class Ausverkauft(Zustand):
    __instance = None  # Das private statische Attribut

    def __new__(cls):
        if cls.__instance is None:
            cls.__instance = super(Ausverkauft, cls).__new__(cls)
        return cls.__instance

    @staticmethod
    def getAusverkauft():
        if Ausverkauft.__instance is None:
            Ausverkauft.__instance = Ausverkauft()
        return Ausverkauft.__instance

    def auswertung(self, konzert):
        # Implementierung der spezifischen Logik für den ausverkauften Zustand
        pass
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Nein, das macht man In Python so nicht.

Zuerst mal das: Zwei führende Unterstriche bedeuten in Python nicht dasselbe wie das private Keyword in Java oder C#. In Python ist nichts wirklich privat. Per Konvention bedeutet ein einzelner führender Unterstrich "Das ist ein Implementationsdetail. Benutzung auf eigene Gefahr." Zwei führende Unterstriche (ohne zwei abschließende) führen zu sog. Private Name Mangling. Das verwendet man in Multiple Inheritance Szenarien um Namenskollisionen zu vermeiden. Es trägt zwar das Wort privat im Namen, hat aber immer noch nichts mit dem private Keyword von Java oder C# zu tun.

Und weil es in Python keine privaten Methoden gibt, gibt es auch keinen privaten Konstruktor. In C/C++/C#/Java gibt es Konstruktorenm die für beides, Erzeugung und Initialisierung, eines Objekts zuständig sind. In Python ist das besser getrennt, weil es sich ja um unterschiedliche Dinge handelt. __new__() wird automagisch aufgerufen und liefert als Ergebnis ein neu erzeugtes Objekt, auf dem dann gleicherweise automagisch __init__() aufgerufen wird. Das ist die Methode, die man üblicherweise selbst implementiert, um ein Objekt zu Initialisieren. __new__() implementiert man nur, wenn man genau weiß, warum man es braucht, und man braucht es fast nie. Ja, man kann darüber ein Singleton erzeugen, indem man einfach immer dasselbe Objekt zurückgibt, so wie in deinem Beispiel. Aber dann greift der folgende Absatz.

Singletons sind generell wenig nützlich. Das letzte Mal hab ich vor >20 Jahren mal eines gebraucht. Statt dessen würde man an dieser Stelle einfach jedesmal nachsehen, wieviele freie Sitze für ein Konzert es noch gibt, und wenn die Anzahl Null ist, ist es eben ausverkauft. Das ist eine transiente Eigenschaft, für die man nicht extra ein Zustandsobjekt erzeugen muss. Was zB. wenn man erlauben möchte, dass Karten zurückgegeben werden können? Dann kann ein vorher ausverkauftes Konzert plötzlich nicht mehr ausverkauft sein.

Ich halte es sowieso nicht für sinnvoll, UML zu verwenden. Meistens kommt dabei doch wieder nur ein Quasi-Entity-Relationship-Diagramm raus, oder gleich bloß ein Relationales Diagramm. Kaum jemand macht sich je die Mühe, Ablauf- oder Zustands-Diagramme zu malen.
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

das ist wie schon erklärt extrem unpythonisch. Und die "Ausverkauft" Klasse ist so oder so komisch - "ausverkauft" ist ein Zustand, denn man mit True/False abbilden kann, also mit einer einzigen Variablen bzw. einem Attribut einer Klasse.

Beschreib' doch mal, was du vor hast bzw. was die Aufgabe ist. Dann hast du bessere Chancen, dass dir reale Menschen den Weg zu besserem Code zeigen.

Gruß, noisefloor
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Auch wenn das Konzept Singleton und der Sinn einer Ausverkauft-Klasse hier schon diskutiert wurden, noch ein paar Anmerkungen zum konkreten Code:
Warum erbt Ausverkauft von Zustand? Abstrakte Klassen machen wegen Ducktyping in Python selten Sinn. Eine Klasse, die nichts kann und nichts macht, kann man auch weglassen.
`super` wird in Python3 üblicherweise ohne Argumente aufgerufen, hier kommt eine Besonderheit von __new__ zu tragen: auch wenn cls das erste Argument ist, ist es keine classmethod, sondern implizit eine staticmethod, so dass cls als Argument an super().__new__ übergeben werden muß.
Eine Methode getAusverkauft ist unnötig, weil dafür gibt es ja schon __new__ und das ist ja die Eigenschaft eines Singletons, dass der Konstruktor dafür sorgt, dass immer nur eine Instanz existiert.
Das hätte aber eigentlich auch schon auffallen müssen, das in beiden Funktionen fast der selbe Code steht.

Code: Alles auswählen

class Ausverkauft:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

    def auswertung(self, konzert):
        # Implementierung der spezifischen Logik für den ausverkauften Zustand
        pass
Aber Singletons braucht man eigentlich nicht, weil man ja einfach nur ein Exemplar der Klasse erzeugen könnte, und entweder als globale Konstante definiert, oder eben sauber überall herumreicht, wo die Instanz gebraucht wird.
magocode
User
Beiträge: 24
Registriert: Dienstag 9. Mai 2023, 08:53

Ich wollte ein UML Diagramm in Python darstellen. Bin Umschüler und bereite mich auf die Abschlussprüfung vor. Denke hat sich erledigt erstmal. Danke
PS: Ich hab nicht das ganze UML Diagramm gezeigt.
Benutzeravatar
__blackjack__
User
Beiträge: 13116
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@magocode: Wenn `Zustand` tatsächlich nur dazu da ist eine einzige Methode bereitzustellen, die eigentlich eine Funktion ist, dann ist der ganze Klassenkram unnütz, denn dann wäre die Umsetzung einfach nur:

Code: Alles auswählen

def ausverkauft_auswerten(konzert):
    ...
Für weitere Zustände dann halt weitere Funktionen. Eine pro Zustand.

Funktionen sind in Python auch Werte, was ein Synonym für Objekte ist, und können als Argumente übergeben werden, als Attribute gesetzt werden, ..., halt alles was man mit Objekten/Werten so machen kann.

Eine Funktion ist auch gleichzeitig ein Singleton ohne das man da noch extra etwas tun muss.

Das ist eines der Probleme mit UML und Python, oder dynamischen Programmiersprachen und/oder Sprachen die nicht zwanghaft alles in Klassen stecken wollen: Da kommt oft überkomplizieter Unsinn für die einfachsten Sachen bei heraus. Der dann auch noch so Magie wie `__new__()` enthält, was man in realem Python, wie ja schon gesagt wurde, nur alle 10 Jahre mal für einen einzelnen Sonderfall tatsächlich benötigt.

Falls Du jetzt sagst weil Du nur einen Teil des UMLs gezeigt hast, geht das nicht mit einer Funktion (oder einem aufrufbaren Wert/Objekt) pro Zustand, dann müsstest Du das ganze relevante UML zeigen. Denn wir können nur was zu dem sagen was wir kennen, und man sollte nicht auf eine vage Beschreibung hin mehr Komplexität in eine Lösung stecken, als nötig ist. KISS-Prinzip.

Und immer dran denken das sprachunabhängige Diagramme in einer konkreten Sprache umzusetzen, nicht bedeutet das das irgendwie 1:1 funktionieren muss, also das man für Klassen die nur eine `__init__()` und eine einzige Methode haben, auch im Programm eine Klasse haben muss, denn meistens sind solche Klassen eigentlich Funktionen. Nur kennt UML das nicht. Genau so eine Klasse mit einem Haufen statischer Methoden: Ist in UML und beispielsweise Java leider nötig das zwanghaft in eine Klasse zu stopfen, in Python sind das einfach Funktionen.

Beziehungsweise wenn man in einer UML-Klasse statische Funktionen hat, die so etwas wie alternative Konstruktoren beziehungsweise Fabrikmethoden sind, dann werden die in Python zu Klassenmethoden. (Gibt es IIRC in UML auch nicht.)
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
magocode
User
Beiträge: 24
Registriert: Dienstag 9. Mai 2023, 08:53

__blackjack__ hat geschrieben: Mittwoch 8. November 2023, 11:56 @magocode: Wenn `Zustand` tatsächlich nur dazu da ist eine einzige Methode bereitzustellen, die eigentlich eine Funktion ist, dann ist der ganze Klassenkram unnütz, denn dann wäre die Umsetzung einfach nur:

Code: Alles auswählen

def ausverkauft_auswerten(konzert):
    ...
Für weitere Zustände dann halt weitere Funktionen. Eine pro Zustand.

Funktionen sind in Python auch Werte, was ein Synonym für Objekte ist, und können als Argumente übergeben werden, als Attribute gesetzt werden, ..., halt alles was man mit Objekten/Werten so machen kann.

Eine Funktion ist auch gleichzeitig ein Singleton ohne das man da noch extra etwas tun muss.

Das ist eines der Probleme mit UML und Python, oder dynamischen Programmiersprachen und/oder Sprachen die nicht zwanghaft alles in Klassen stecken wollen: Da kommt oft überkomplizieter Unsinn für die einfachsten Sachen bei heraus. Der dann auch noch so Magie wie `__new__()` enthält, was man in realem Python, wie ja schon gesagt wurde, nur alle 10 Jahre mal für einen einzelnen Sonderfall tatsächlich benötigt.

Falls Du jetzt sagst weil Du nur einen Teil des UMLs gezeigt hast, geht das nicht mit einer Funktion (oder einem aufrufbaren Wert/Objekt) pro Zustand, dann müsstest Du das ganze relevante UML zeigen. Denn wir können nur was zu dem sagen was wir kennen, und man sollte nicht auf eine vage Beschreibung hin mehr Komplexität in eine Lösung stecken, als nötig ist. KISS-Prinzip.

Und immer dran denken das sprachunabhängige Diagramme in einer konkreten Sprache umzusetzen, nicht bedeutet das das irgendwie 1:1 funktionieren muss, also das man für Klassen die nur eine `__init__()` und eine einzige Methode haben, auch im Programm eine Klasse haben muss, denn meistens sind solche Klassen eigentlich Funktionen. Nur kennt UML das nicht. Genau so eine Klasse mit einem Haufen statischer Methoden: Ist in UML und beispielsweise Java leider nötig das zwanghaft in eine Klasse zu stopfen, in Python sind das einfach Funktionen.

Beziehungsweise wenn man in einer UML-Klasse statische Funktionen hat, die so etwas wie alternative Konstruktoren beziehungsweise Fabrikmethoden sind, dann werden die in Python zu Klassenmethoden. (Gibt es IIRC in UML auch nicht.)
Bilder kann man hier nicht hochladen oder? Und danke für die ausführliche Antwort
Benutzeravatar
__blackjack__
User
Beiträge: 13116
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Bilder kann man bei einem externen Hoster, beispielsweise Imgur hochladen und dann hier einbinden. Wichtig ist, dass das BBCode [img‍]-Tag die URL zu der Bilddatei braucht und nicht zu einer Webseite wo das Bild enthalten ist.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten