kleine Mathe-Spielereien

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Benutzeravatar
__blackjack__
User
Beiträge: 14027
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: 6861
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: 6861
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: 589
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: 6861
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: 589
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: 14027
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: 6861
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.
OSWALD
User
Beiträge: 589
Registriert: Freitag 18. März 2022, 17:32

11.7.2025
@blackjack und snafu ,
sowie all den anderen Moderatoren,
die mich beim Versuch Python zun erlernen , so sehr
kritisch aber erfolgreich unterstützt haben.
Python ist mein Hobby und neben Büchern kann ich nur
aus konkreten Beispielen im Internet die notwendigen
Informationen gewinnen.
Ich dabei gelernt, dass das Internet auch sehr viele
unbrauchbare Informationen liefert .
Das Angebot an Kursen ist riesig und klingt oft mehr
wie eine Rabatt-Aktion.
Was OOP anbelangt werde ich mich weiterhin bemühen,
die klassschen Prinzipien der OOP zu verfolgen., von denen
im Netz kaum noch etwas zu finden ist und "Zeit lassen ".
Ich habe diesen Artikel gefunden. ???
####https://avant-iconic.com/was-ist-mit-oop-los/
Gute Zeit OSWALD
Benutzeravatar
Dennis89
User
Beiträge: 1532
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,

als Start: https://docs.python.org/3/tutorial/classes.html

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
snafu
User
Beiträge: 6861
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@Oswald
Und genau deshalb ist es gut, dass Python nicht den Weg von Java eingeschlagen hat und den OOP Style nicht erzwingt. Vieles klappt viel besser mit Funktionen. OOP nutze ich meist erst dann, wenn es komplizierter wird, weil mir das beim Strukturieren hilft. Die "reine" OOP hat man in der Praxis tatsächlich nicht, sondern eine Mischform. Daher schrieb ich bewusst von der "Idee" hinter OOP. Nur deins war IMHO komplett am Thema vorbei. Gerade auch weil du ein typisches OOP Beispiel geben wolltest.
Benutzeravatar
__blackjack__
User
Beiträge: 14027
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@snafu: Naja, man kann aber auch sagen, das Python mehr OOP als Java ist, weil in Python *alles* was man an einen Namen binden kann ein Objekt ist, auch Funktionen. Und man kann nicht nur Nachrichten an ”Slots” von Objekten schicken, sondern es gibt einen ”Slot” mit dem man das Objekt ”direkt” ansprechen kann (`__call__()`). Womit man Funktionsobjekten direkt Nachrichten schicken kann, auf die sie Antworten können. Das lässt sich alles mit OOP-sprech erklären/beschreiben, wenn man möchte. Klassische OOP-Sprachen wie Smalltalk oder aktuelleres wie Io fühlt sich in der idiomatischen Handhabung oft deutlich funktionaler an als Java. Und selbst Java hat ja mittlerweile syntaktischen Zucker um Klassen mit einer Methode wie Funktionen aussehen zu lassen. Inklusive anonymer Klassen in dem Format als `lambda`-Ausdruck schreiben zu können.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
OSWALD
User
Beiträge: 589
Registriert: Freitag 18. März 2022, 17:32

11.7.2025
Ich beschäftige mich seit einiger Zeit mit 'callback'
und habe mich mit einigen Programmen auseiandergesetzt, wobei es
überhaupt nicht einfach war, sofort des Pudels Kern zu erfassen.
Jetzt ist mir aber allse klar, dank diesem kleinen Code, den ich zufällig
bei GUI wiederentdeckt habe.
OSWALD

[code

#Eine GUIAnwendung mit Callback
import tkinter

#Funktion zu Schaltfläche Ende

def Ende(): #callback ?
main.distroy()

#Hauptfenster
main =tkinter.Tk()

# Schaltfläche Ende
b =tkinter .Button(main,text = "Ende",command =Ende)
b=pack()

#Endlosschleife
main.mainloop


[/code]
Benutzeravatar
snafu
User
Beiträge: 6861
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Die Mischform bezog ich nicht auf die Beschaffenheit der Sprache, sondern auf die Anwendung des OOP-Prinzips seitens des Programmierers. Selbst in populären Projekten gibt es Bereiche, wo Funktionalität zu einem bestimmten Thema als Methoden an eine Klasse "geheftet" wird, die man genau so gut als Funktionen auf Modulebene realisieren könnte.

Es ist natürlich auch immer die Frage, wo man die Grenze zieht. Ein als Klasse realisierter Parser etwa passt nicht so sehr auf die Idee, dass Klassen primär für die Datenhaltung gedacht sind. Trotzdem kann es praktische Gründe geben, dass man sich für die Klasse entschieden hat. Das spricht der von OSWALD verlinkte Text ja auch ein bisschen an.
OSWALD
User
Beiträge: 589
Registriert: Freitag 18. März 2022, 17:32

11.7.2025
Und hier noch ein Beispiel für die callbackFunktion
aus dem GUI-Bereich.

NB im obigen Code zu callback hat sich mit b= pack()
ein Fehler eingeschlichen, bitte b=pack löschen
OSWALD

Code: Alles auswählen


import tkinter as tk

def button_click():
    """Wird aufgerufen, wenn der Button geklickt wird."""
    label.config(text="Button wurde geklickt!")

def entry_change(event):
    """Wird aufgerufen, wenn sich der Inhalt des Eingabefeldes ändert."""
    label.config(text=f"Eingabe: {entry.get()}")

# Fenster erstellen
root = tk.Tk()
root.title("Callback Beispiel")

# Button erstellen und Callback zuweisen
button = tk.Button(root, text="Klick mich", command=button_click)
button.pack(pady=10)

# Eingabefeld erstellen und Callback zuweisen
entry = tk.Entry(root)
entry.bind("<KeyRelease>", entry_change)  # Callback bei jeder Tastenfreigabe
entry.pack()

# Label für die Ausgabe erstellen
label = tk.Label(root, text="Noch nichts passiert")
label.pack()

root.mainloop()

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

@OSWALD Beide Beispiele sind nicht gut, weil in ”Funktionen” auf globale Werte zugegriffen wird.

Code: Alles auswählen

#!/usr/bin/env python3
import tkinter as tk
from functools import partial


def on_button_click(label):
    label.config(text="Button wurde geklickt!")


def on_entry_change(label, event):
    label.config(text=f"Eingabe: {event.widget.get()}")


def main():
    root = tk.Tk()
    root.title("Callback Beispiel")

    button = tk.Button(root, text="Klick mich")
    button.pack(pady=10)

    entry = tk.Entry(root)
    entry.pack()

    label = tk.Label(root, text="Noch nichts passiert")
    label.pack()

    button.config(command=partial(on_button_click, label))
    entry.bind("<KeyRelease>", partial(on_entry_change, label))

    root.mainloop()


if __name__ == "__main__":
    main()
Edit: Oder mit Klasse:

Code: Alles auswählen

#!/usr/bin/env python3
import tkinter as tk


class MainWindow(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.title("Callback Beispiel")

        tk.Button(self, text="Klick mich", command=self.on_button_click).pack(
            pady=10
        )

        self.entry = tk.Entry(self)
        self.entry.bind("<KeyRelease>", self.on_entry_change)
        self.entry.pack()

        self.label = tk.Label(self, text="Noch nichts passiert")
        self.label.pack()

    def on_button_click(self):
        self.label.config(text="Button wurde geklickt!")

    def on_entry_change(self, _event):
        self.label.config(text=f"Eingabe: {self.entry.get()}")


def main():
    MainWindow().mainloop()


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.
Antworten