kleine Mathe-Spielereien

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Benutzeravatar
__blackjack__
User
Beiträge: 14023
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Klassenvariablen sind globaler Zustand, darum ist das nicht gut da tatsächlich Variablen zu haben, aber es kann Sinn machen Konstanten zu definieren die an Klassen gebunden sind. Also der Umstand das man auf dieser Ebene Namen definieren kann, ist nicht nutzlos.

Und mit Metaklassen oder Klassendekoratoren kann es auch Sinn machen Informationen auf Klassenebene zu definieren, die dann verwendet werden können um die Klasse konkreter zu beschreiben und beim erstellen der Klasse ausgewertet zu werden. Ein Beispiel dafür — `dataclasses` — haben wir hier ja gerade gesehen. Ein anderes Beispiel in der Standardbibliothek wäre das `ctypes`-Modul aus der Standardbibliothek.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Benutzeravatar
snafu
User
Beiträge: 6859
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

OSWALD hat geschrieben: Sonntag 6. Juli 2025, 10:25 Ich zeige hier hier ein analoges Beispiel (...)
Welche Analogie soll das sein? Du hast eine Wall-Klasse und machst "ungesunde" Dinge mit dessen Klassenattribut. Geht es dir darum, dass es polymorph wäre, weil sich die Veränderung auf alle erzeugten Objekte der Klasse auswirkt? Dann hast du das Thema offensichtlich nach wie vor nicht verstanden.

Vielleicht würde es dir helfen, die Sache mit Java anzugehen. Denn da muss man den Typ explizit hinschreiben. Seit Java 10 gibt es zwar "var" (also doch schon einige Jahre), wodurch der Zwang zur Typangabe wegfallen kann, aber das muss man ja nicht unbedingt verwenden.

Bei einer schnellen Suche nach "java polymorphism example" fand ich jedenfalls diese Beschreibung am besten, weil dort mit der Elternklasse deklariert, aber mit der Kindklasse initialisiert wird. Das fehlte mir bei einigen anderen Beispielen. Die Frage ist aber ehrlich gesagt auch, ob du dieses Thema nicht vielleicht nach hinten schieben solltest.
Benutzeravatar
snafu
User
Beiträge: 6859
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

In der Praxis arbeiten wir natürlich nicht mit Hunden und Katzen. Neben dem Beispiel mit der Länge und der Addition fällt mir noch ein weiterer typischer Anwendungsfall für Python ein, den ich selber oft für meine Funktionen verwende: Iterable.

Da wird also ein Container mit Elementen erwartet, damit mit diesen Elementen etwas gemacht werden kann. Es muss aber nicht zwingend eine Liste oder sonstiger konkreter Typ sein, sondern einfach etwas, das ich mit einer for-Schleife benutzen kann.

Daher geht man hier vom abstrakten Typen aus:

Code: Alles auswählen

def handle_items(iterable):
    for item in iterable:
        # ...
Dies funktioniert mit jeder Klasse, die das Iterator-Protokoll implementiert, analog zu den bei Java bekannten Schnittstellen, die ja auch in meinem Link erwähnt wurden. Damit bekommt man Polymorphismus in Python, möglicherweise ohne dass es einem bisher bewusst war. :)
OSWALD
User
Beiträge: 586
Registriert: Freitag 18. März 2022, 17:32

7.7.25
'Hier steh' ich nun ich armer Tor.....'
und frage, " welchen Polymorphismus" soll ich nun auswählen,
um es jemals verstehen zu können?
Ich verfüge nicht über metaphorische Fähigkeiten.
Hier wäre die Auswahl;
OSWALD
Arten von Polymorphismus
In der Computerprogrammierung gibt es zwei Hauptarten von Polymorphismus:

Polymorphismus zur Kompilierzeit.

Der auch als statischer Polymorphismus bekannte Polymorphismus zur Kompilierzeit
ist in OOP-Sprachen wie Java weit verbreitet.
Sie verwendet die Methodenüberladung, um mehrere Methoden zu erstellen,
die in derselben Klasse denselben Namen,
aber eine unterschiedliche Anzahl von Parametern haben.
Sie können auch Parameter für unterschiedliche Datentypen haben.

Polymorphismus zur Laufzeit.
Nix für ungut
OSWALD
##############################
Der Laufzeit-Polymorphismus, der auch als dynamischer Polymorphismus bezeichnet wird,
verwendet Methodenüberladung, damit eine untergeordnete Klasse ihre eigene Definition
einer Methode der übergeordneten Klasse hat.
Diese Art der Polymorphie wird oft mit Upcasting in Verbindung gebracht,
wenn eine Elternklasse auf eine Instanz der Kindklasse verweist.
Polymorphismus kann in der OOP auch auf andere Weise implementiert werden, zum Beispiel:

Ad-hoc-Polymorphismus.
Eine Funktion wird auf verschiedene Argumente angewandt und kann je nach Art des Arguments unterschiedlich funktionieren.

Parametrischer Polymorphismus.
Programmierer können generische Funktionen schreiben, die Werte in einem Datensatz unabhängig von ihrem Typ auf die gleiche Weise behandeln.

Subtyping-Polymorphismus.
Programmierer können mehrere Funktionen oder Unterprogramme erstellen, die auf der Supertyp-Klasse und auf verschiedenen Subtypen arbeiten können.

Zeilen-Polymorphismus.
Programmierer können Programme schreiben,
die sich nur auf einen bestimmten Abschnitt eines Datenbankdatensatzes,
das heißt eine Zeile, auswirken.

#################################
Benutzeravatar
snafu
User
Beiträge: 6859
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Uns sieh dir mal erst Kreise an. Die treten auch in total unterschiedlichen Formen auf. Zum Beispiel am Fahrrad oder als Alternative zu einer Kreuzung oder als Schallplatte. Und manchmal dreht man sich auch einfach im Kreis. Total verrückt, oder? Was ist denn nun der richtige Kreis?

Vielleicht beantwortet es dieser Song, vielleicht aber auch nicht:
https://www.youtube.com/watch?v=apCal7ihvy0
OSWALD
User
Beiträge: 586
Registriert: Freitag 18. März 2022, 17:32

10.7.2025
Aufgeben heisst verlieren.
Deshalb nochein Versuch
OSWALD

Code: Alles auswählen


class Student:
    def __init__(self, name):
        self.name = name

    def ausgeben(self):
        print("ein Student")

#  POLYMORPHIE                   in   PYTHON
class Anna(Student):
    def __init__(self, name):
        super().__init__(name)                  #hier spielt die Musik

    def ausgeben(self):
        print(f"Anna  studiert   {self.name}")


class Hans(Student):
    def __init__(self, name):
        super().__init__(name)

    def ausgeben(self):
        print(f"Hans studiert   {self.name}")


class Walter(Student):
    def __init__(self, name):
        super().__init__(name)

    def ausgeben(self):
        print(f"Walter studiert  {self.name}")


#  Istm das jetzt Polymorphie ???
Student = [Anna("Medizin"), Hans("Physik"), Walter("Informatik")]

for Student  in Student:
    Student.ausgeben()






Benutzeravatar
__blackjack__
User
Beiträge: 14023
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@OSWALD: `Student.name` ist das *Fach* das studiert wird und nicht der Name des Studenten? Das ist, äh, überraschend.

Pro konkretem Student dann jeweils eine Klasse abzuleiten und den Klassennamen in einer Methode in einer Zeichenkette jedes mal zu wiederholen ist unsinnig.

Der Name `Sudent` wird für die Klasse, für eine Liste mit `Student`-Objekten, und dann noch mal für einzelne Studenten verwendet. Das ist verwirrend und nach dem die Ausgabeschleife gelaufen ist, kommt man deswegen weder an die Klasse noch an die Liste mehr heran, weil der Name dann ja an den letzten Studenten aus der Liste gebunden ist.

Das Beispiel wäre eher folgendes und ist dann wegen `__str__()` ein Beispiel für Polymorphie, weil es wie andere Objekte auch mit `str()` in eine Zeichenkette gewandelt werden kann, was `print()` intern macht:

Code: Alles auswählen

#!/usr/bin/env python3


class Student:
    def __init__(self, name, fach):
        self.name = name
        self.fach = fach

    def __str__(self):
        return f"{self.name} studiert {self.fach}."


def main():
    studenten = [
        Student("Anna", "Medizin"),
        Student("Hans", "Physik"),
        Student("Walter", "Informatik"),
    ]
    for student in studenten:
        print(student)


if __name__ == "__main__":
    main()
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Benutzeravatar
snafu
User
Beiträge: 6859
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ich versuch's nochmal: Von der grundsätzlichen Idee her ist eine Klasse eine Kategorie bzw. Art von etwas. Von einem Exemplar oder einer Instanz der Klasse spricht man, wenn man ein Objekt einer Kategorie hat. Wenn die Klasse zum Beispiel "Hund" ist, dann sind Fiffi und Waldi die Exemplare. Wohingegen Dackel und Pudel abgeleitete Klassen von "Hund" sein könnten. Letzteres würde ich aber nur dann machen, wenn die abgeleiteten Klassen ein jeweils eigenes Verhalten implementiert haben. Andernfalls würde ich für die Klasse "Hund" abgesehen vom Namen noch das Attribut "rasse" definieren und dort "dackel" oder "pudel" eintragen.

Wir waren hier auch schon einmal bei der Feststellung, dass eine Klasse so eine Art Bauplan ist, der Eigenschaften und Verhalten definiert. Klar kann ich jetzt so weit gehen, dass jeder Student einzigartig ist und somit ein eigenes Verhalten hat. Aber im Kontext der IT wäre die Klasse "Student" eine Ansammlung von Daten. Und die sind für einen Walter nicht anders strukturiert als für eine Anna. Das Verhalten könnte die überblicksartige Ausgabe der zugehörigen Daten als String sein. Ein weiteres Beispiel wäre das Anmelden für eine Veranstaltung (bei Erfolg: Eintrag der Veranstaltung in den internen Daten, bei Misserfolg eine Fehlermeldung mit Begründung an den Benutzer).

@OSWALD: Ich finde ja, man sollte erst einmal die Idee von Klassen verstanden haben, bevor man sich komplexeren Themen wie Vererbung oder Polymorphismus zuwendet. Dein letztes Beispiel hat IMHO sehr deutlich gemacht, dass da noch viel Luft nach oben bei dir ist. Dein Wissensdrang in Ehren, aber es bringt doch wenig, wenn das Vorgehen zu mehr Verwirrung als zu einem Erkenntnisgewinn führt.

Übrigens, du hast "Hier spielt die Musik" an die __init__()-Methode einer abgeleiteten Klasse geschrieben. Aber genau da spielt sie nicht. Denn diese __init__() wiederholt das Verhalten, das man bei Vererbung sowieso schon hat. Das ist im Endeffekt so als wenn du eine Zeile ausradierst und das gleiche nochmal hinschreibst. Der Effekt der Vererbung erfolgt an der Stelle, wo du ``Hans(Student)`` schreibst. Da passiert bei der Codeausführung die ganze "Magie", weil sich der Hans an der Stelle den Studenten-Bauplan sozusagen einverleibt. Ein Überschreiben des übernommenen Verhaltens, so wie du es tust, macht diesen Effekt wieder zunichte.
Antworten