Seite 35 von 36
Re: kleine Mathe-Spielereien
Verfasst: Montag 23. Juni 2025, 16:07
von OSWALD
23.6.2025
von 'class angebot'
habe ich mir eine weitere Version gebastelt.
'Übung macht den Meister' und ist besser lesbar.
OSWALD
Code: Alles auswählen
KIOSK VERKSUFSANGEBOT
class Angebot:
def __init__(self, product_id, name, price, quantity, **kwargs):
self.product_id = product_id
self.name = name
self.price = price
self.quantity = quantity
## Add any additional attributes provided
for key, value in kwargs.items():
setattr(self, key, value)
def total_value(self):
return self.price * self.quantity
def display_info(self):
result = [f"Angebot: {self.name} (ID: {self.product_id})",
f"Price: €{self.price:.2f}",
f"Quantity: {self.quantity}",
f"Total Value: €{self.total_value():.2f}"]
## Display additional attributes
standard_attrs = {'product_id', 'name', 'price', 'quantity'}
for attr in dir(self):
if not attr.startswith('__') and not callable(getattr(self, attr)) and attr not in standard_attrs:
value = getattr(self, attr)
result.append(f"{attr.replace('_', ' ').title()}: {value}")
return '\n'.join(result)
class Verkauf:
def __init__(self):
self.products = {}
def add_product(self, product):
self.products[product.product_id] = product
print(f"Added: {product.name}")
def update_attribute(self, product_id, attribute, value):
if product_id in self.products:
product = self.products[product_id]
old_value = getattr(product, attribute, None)
setattr(product, attribute, value)
print(f"Updated {attribute} of {product.name} from {old_value} to {value}")
return True
print(f"Product with ID {product_id} not found.")
return False
def display_verkauf(self):
if not self.products:
print("Verkauf")
return
print("\n===== Current Inventory =====")
total_value = 0
for product in self.products.values():
print(f"\n{product.display_info()}")
total_value += product.total_value()
print(f"\nTotal Verkauf Value: €{total_value:.2f}")
print("============================")
print("#IMPLENTIEREN #################################")
verkauf = Verkauf()
## Create products with additional attributes
kaffee = Angebot(1, "Kaffee", 3.50, 5)
wiener = Angebot(2, "Wiener", 4, 10)
eiskaffee =Angebot(3, "Eiskaffee ",6 ,25)
bratwurst = Angebot(4, "Bratwurst", 9, 5)
kuchen = Angebot(5,"Kuchen",3.50,7)
## Verkaufte Produkte
verkauf.add_product(kaffee)
verkauf.add_product(wiener)
verkauf.add_product(eiskaffee)
verkauf.add_product(bratwurst)
verkauf.add_product(kuchen)
## Display the inventory
verkauf.display_verkauf()
## Update a standard attribute
verkauf.update_attribute(5, "price", 5)
verkauf.update_attribute(4, "price" ,3)
## Update a custom attribute
## Add a new attribute to an existing product
verkauf.update_attribute(2, "price", 13)
## Display the updated inventory
verkauf.display_verkauf()
Re: kleine Mathe-Spielereien
Verfasst: Montag 23. Juni 2025, 17:47
von snafu
OSWALD hat geschrieben: Montag 23. Juni 2025, 15:32
3.' OOP- Class ' scheint mir für 'Zahlenthemen' besser geeignet als für Strings
OOP ist einfach die Kapselung von Zustand, Verhalten und Logik. Vor allem kann man sich den Zustand damit relativ einfach über mehrere Aufrufe merken bzw. verwenden. Außerdem erscheint OOP - wenn richtig angewendet - oft "greifbarer", weil man sich reale Objekte dahinter vorstellen kann.
Ein gutes OOP-Design ist allerdings sehr herausfordernd. Du bist quasi der Architekt deiner "Objekt-Welt". Man erwischt sich schnell dabei, dass man stellenweise eigentlich nur eine Ansammlung von Funktionen gebastelt hat, die sich via "self" aufrufen und trotzdem das gleiche Argument herumreichen. Wenn man so etwas hat, sollte man den Ansatz infrage stellen und überlegen, wie man mehr Objektorientierung hinein bekommt.
Jedenfalls lässt sich das nicht an der Frage festmachen, ob man Zahlen oder Strings vorliegen hat. Python selbst hat - wie viele andere Sprachen auch - den Datentyp "str" als Objekt mit Methoden implementiert. Warum sollte das weniger gut für OOP geeignet sein als eine zahlenlastige Klasse?
Im Übrigen sind simple String-Kodierungen wie ASCII nichts anderes als eine Zahlenfolge, welche die Positionen der einzelnen Zeichen im vorliegenden Zeichensatz angeben. Und in komplexeren Formaten wie Unicode stecken mehr logische Operationen mit Zahlen als du vielleicht denkst.
Re: kleine Mathe-Spielereien
Verfasst: Dienstag 24. Juni 2025, 08:16
von OSWALD
24.6.2025
An snafu
Als Lehrling hier im Forum würde ich mir nie erlauben
auch nur die geringste Kritik an Python bzw. OOP zu üben.
Ich hätte vielleicht sagen sollen, dass mir generell als
Zahlenmensch der Umgang mit 'strings' viel schwerer
erscheint als der mit Zahlen. Das ist mir bei der Beschäftigung
mit Matrizen besonders aufgefallen.
Das Prinzip *Form und Inhalt* ist halt immer sehr schwer zu realisieren.
Die Voraussetzungen für das Erlernen und Verstehen von Python etwa
sind schon sehr hoch, weil Python selbst genial und sehr komplex ist.
Python ist mein Hobby
Re: kleine Mathe-Spielereien
Verfasst: Dienstag 24. Juni 2025, 15:04
von OSWALD
24.6.25
OOP
Hier zunächst das Prinzip der Vererbung.
Ausführliches Beispiel folgt.
OSWALD
Code: Alles auswählen
#VERERBUNG TIER >>>>>> BauplanHundeKlasse(Tier)
#YERERBUNG TIER >>>>>>>BauplanVÖGELKlasse(Tier)
class Tier():
def __init__(self, rufname, farbe, alter):
self.rufname = rufname
self.farbe = farbe
self.alter = alter
##################################
class BauplanHundeKlasse(Tier):
""
def __init__(self, rufname, farbe, alter):
""" Initalisieren über Eltern-Klasse """
super().__init__(rufname, farbe, alter)
hund_wauwau = BauplanHundeKlasse("Wauwau", "braun", 6)
print(hund_wauwau.farbe)
##############################
class BauplanVogelKlasse(Tier):
def __init__(self, rufname, farbe, alter): ### hier Initialisierung
""" Initalisieren über Eltern-Klasse """
super().__init__(rufname, farbe, alter)
papagei_lora = BauplanVogelKlasse("Lora", "bunt", 5)
print(papagei_lora.rufname)
Re: kleine Mathe-Spielereien
Verfasst: Dienstag 24. Juni 2025, 15:13
von __blackjack__
Das ist vielleicht syntaktisch ein Beispiel für Vererbung aber inhaltlich nicht. Und die `__init__()`-Methoden bei den abgeleiteten Klassen machen nichts sinnvolles, die kann man einfach weglassen, ohne das sich etwas am Programmablauf verändert.
Die Namensgebung macht auch keinen Sinn. Ja Klassen sind Klassen. Und Klassen sind Baupläne. Das bringt also nichts das noch mal im Klassennamen zu erwähnen. `Tier` heisst ja auch nicht `BauplanTierKlasse`, obwohl auch das ein Bauplan/eine Klasse ist.
Re: kleine Mathe-Spielereien
Verfasst: Mittwoch 25. Juni 2025, 07:42
von OSWALD
25.6.25
@blackjack
diese Definition habe ich dem Internet entnommen ,weil
die mir bisher bekannte Syntax des Begriffes Vererbung etwas
anders aussah( 'super' ??? usw).
Nun hoffe ich, dass jetzt alles stimmt.
Hier meine Version für Vererbung.
Gute Zeit OSWALD
Code: Alles auswählen
class Konto(object):
""" Basis Konto Klasse """
def __init__(self, inhaber, kontonummer, kontostand):
""" Konstruktor, Aufruf bei Instanzierung """
print( ".. Konto anlegen")
self.Inhaber = inhaber
self.Kontonummer = kontonummer
self.Kontostand = kontostand
self.zeige_konto()
def einzahlen(self, betrag):
""" Mach eine Einzahlung """
print (".. Einzahlen : %i %5.1f" % (self.Kontonummer, betrag))
self.Kontostand += betrag
def auszahlen(self, betrag):
""" Mach eine Auszahlung """
print( ".. Auszahlen : %i %5.1f" % (self.Kontonummer, betrag))
self.Kontostand -= betrag
##########Achtung die Methode ueberweisung wurde aus Class Girokonto nach class Konto kopiert
def ueberweisung(self, ziel, betrag):
""" Mach eine Ueberweisung """
print( ".. Transfer : %i %s %i %5.1f" % (self.Kontonummer, "->", ziel.Kontonummer, betrag))
self.Kontostand -= betrag
ziel.Kontostand += betrag
def zeige_konto(self):
""" Zeige die Kontodaten am Bildschirm """
print( ".. Konto :", self.Inhaber)
print( " Kontonummer :", self.Kontonummer)
print( " Kontostand :", self.Kontostand )
#############################
class Girokonto(Konto):
""" Giro Konto Klasse """
def __init__(self, inhaber, kontonummer, kontostand, sollzinsen, habenzinsen):
""" Giro Konstruktor, Aufruf bei Instanzierung """
self.__Sollzinsen = sollzinsen
self.__Habenzinsen = habenzinsen
# initialisiere Konto
Konto.__init__(self, inhaber, kontonummer, kontostand)
############# Hier liegr der Hund begraben
def ueberweisung(self, ziel, betrag):
""" Mach eine Ueberweisung """
print( ".. Transfer : %i %s %i %5.1f" % (self.Kontonummer, "->", ziel.Kontonummer, betrag))
self.Kontostand -= betrag
ziel.Kontostand += betrag
##################################
class Sparkonto(Konto):
""" Sparbuch Konto Klasse """
def __init__(self, inhaber, kontonummer, kontostand, zinssatz):
""" Spar Konstruktor, Aufruf bei Instanzierung """
self.Zinssatz = zinssatz
# initialisiere des Kontos
Konto.__init__(self, inhaber, kontonummer, kontostand)
def zeige_konto(self):
""" Zeige die Kontodaten am Bildschirm, ueberschreibt Konto Funktion """
Konto.zeige_konto(self)
print( (" Zinssatz :", self.Zinssatz ))
if __name__ == '__main__':
print( "\nKontobeispiel mit Vererbung")
# Erzeuge zwei Konto-Objekte
kg = Girokonto("Oswald Meier", 78340, 120, 0.05, 0.01)
ks = Sparkonto("Oswald Meier", 78341, 40.0, 0.03)
km= Konto("Klaus Freund",78200, 50)
km = Girokonto("Klaus Freund", 78300, 150, 0.05,0.01)
print( "------------------------------")
# Mach was damit ...
print("=Oswald Meier zahlt ein auf Girokonto:")
kg.einzahlen(333333)
print("Oswald Meier zahlt ein auf Sparkonto")
ks.einzahlen(5555)
print("Oswald Meier zahlt aus von Sparkonto")
kg.auszahlen(0)
print("Oswald Meier überweist von Giro - auf Sparkonto")
kg.ueberweisung(ks, 10000)
ks.auszahlen (3000)
print("Klaus Freund zahlt auf sein Konto Nr.78200 ein")
km.einzahlen(3000)
print("Klaus Freund zahlt von seinem Konto Nr.78200 aus")
km.auszahlen (400)
km.ueberweisung(ks , 500)
print("Überweisung Versuch von Konto nach Girokonto")
km.ueberweisung(ks,468)
print( "------------------------------")
# Zeige Kontodaten am Bildschirm
kg.zeige_konto()
ks.zeige_konto()
km.zeige_konto()
Re: kleine Mathe-Spielereien
Verfasst: Mittwoch 25. Juni 2025, 08:22
von Dennis89
Hallo,
wenn du von einer Klasse erbst dann hast du dadurch in der Kind-Klasse die Methoden der Eltern-Klasse. Du kannst die überschreiben, wenn sie was anderes machen sollen und das Sinn macht.
Siehe bei dir `ueberweisung`. `zeige_konto`ist etwas komisch wie du die Methode überschrieben hast. Das würde ich nicht machen, sondern die Methode der Eltern-Klasse aufrufen und den Zinssatz extra. Dann will man auf die Instanz zugreifen, also mit `self` und nicht auf das Objekt `Konto`. Aber der Teil fällt eh raus.
Wenn du das änders, dann kannst du die Unterscheidungsmerkmale der Kontentypen einfügen.
Grüße
Dennis
Re: kleine Mathe-Spielereien
Verfasst: Mittwoch 25. Juni 2025, 14:56
von OSWALD
24.6.25
So, jetzt habe ich ein erstes Update hergestellt.
Allen Kram beseitigt,
Code lesbarer gemacht,
und versucht die Regeln von Python zu befolgen.
Ich sehe keinen Fehler mehr(??)
Das Programm ist beliebig erweiterbar.
Aber ein schönes Stück Arbeit.
Gute Zeit OSWALD
Code: Alles auswählen
class Konto(object):
""" Basis Konto Klasse """
def __init__(self, inhaber, kontonummer, kontostand):
""" Konstruktor, Aufruf bei Instanzierung """
print( ".. Konto anlegen")
self.Inhaber = inhaber
self.Kontonummer = kontonummer
self.Kontostand = kontostand
self.zeige_konto()
def einzahlen(self, betrag):
""" Mach eine Einzahlung """
print (".. Einzahlen : %i %5.1f" % (self.Kontonummer, betrag))
self.Kontostand += betrag
def auszahlen(self, betrag):
""" Mach eine Auszahlung """
print( ".. Auszahlen : %i %5.1f" % (self.Kontonummer, betrag))
self.Kontostand -= betrag
##########Achtung die Methode ueberweisung wurde aus Class Girokonto nach class Konto kopiert
def ueberweisung(self, ziel, betrag):
""" Mach eine Ueberweisung """
print( ".. Transfer : %i %s %i %5.1f" % (self.Kontonummer, "->", ziel.Kontonummer, betrag))
self.Kontostand -= betrag
ziel.Kontostand += betrag
def zeige_konto(self):
""" Zeige die Kontodaten am Bildschirm """
print( ".. Konto :", self.Inhaber)
print( " Kontonummer :", self.Kontonummer)
print( " Kontostand :", self.Kontostand )
#############################
class Girokonto(Konto):
""" Giro Konto Klasse """
def __init__(self, inhaber, kontonummer, kontostand, sollzinsen, habenzinsen):
""" Giro Konstruktor, Aufruf bei Instanzierung """
self.__Sollzinsen = sollzinsen
self.__Habenzinsen = habenzinsen
# initialisiere Konto
Konto.__init__(self, inhaber, kontonummer, kontostand)
############# Hier liegr der Hund begraben
def ueberweisung(self, ziel, betrag):
""" Mach eine Ueberweisung """
print( ".. Transfer : %i %s %i %5.1f" % (self.Kontonummer, "->", ziel.Kontonummer, betrag))
self.Kontostand -= betrag
ziel.Kontostand += betrag
##################################
class Sparkonto(Konto):
""" Sparbuch Konto Klasse """
def __init__(self, inhaber, kontonummer, kontostand, zinssatz):
""" Spar Konstruktor, Aufruf bei Instanzierung """
self.Zinssatz = zinssatz
# initialisiere des Kontos
Konto.__init__(self, inhaber, kontonummer, kontostand)
def zeige_konto(self):
""" Zeige die Kontodaten am Bildschirm, ueberschreibt Konto Funktion """
Konto.zeige_konto(self)
print( (" Zinssatz :", self.Zinssatz ))
if __name__ == '__main__':
print(" Neues Konto erstellen ")
kgiro = Girokonto("Oswald Meier", 78340, 120, 0.05, 0.01)
kspar = Sparkonto("Oswald Meier", 78341, 40.0, 0.03)
print()
kgiro= Girokonto("Klaus Freund",78200, 50, 0.04, 0.01)
kspar = Sparkonto("Klaus Freund", 78300, 150, 0.05)
print( " Jetzt Konten bearbeiten")
print("= Oswald Meier zahlt auf sein Girokonto ein :")
kgiro.einzahlen(333333)
print(" Oswald Meier zahlt auf sein Sparkonto ein ")
kspar.einzahlen(5555)
print(" Oswald Meier zahlt aus von Sparkonto")
kgiro.auszahlen(0)
print(" Oswald Meier überweist von Giro - auf Sparkonto")
kgiro.ueberweisung(kspar, 10000)
kspar.auszahlen (3000)
print()
print(" GIRO ktueller Kontostand ")
kgiro.zeige_konto()
print(" SPAR aktueller Kontostand ")
kspar.zeige_konto()
print()
print( " Jetzt Konten bearbeiten")
print()
print("Klaus Freund zahlt auf sein Konto Nr.78300 ein")
kgiro.einzahlen(3000)
print("Klaus Freund zahlt von seinem Konto Nr.78200 aus")
kgiro.auszahlen (400)
kgiro.ueberweisung(kspar , 500)
print("Überweisung Versuch von Konto nach Girokonto")
kspar.ueberweisung(kgiro,468)
print()
print(" GIRO ktueller Kontostand ")
kgiro.zeige_konto()
print(" SPAR aktueller Kontostand ")
kspar.zeige_konto()
print()
Re: kleine Mathe-Spielereien
Verfasst: Mittwoch 25. Juni 2025, 15:53
von grubenfox
Der begrabene Hund (die Methode 'ueberweisung' in der Klasse GiroKonto) ist aktuell mindestens überflüssig und kann weg.
Und wenn man das Programm laufen lässt und sich die ausgegebenen Informationen anschaut, dann stellt man fest dass zum Teil die falschen Konten genutzt werden. Das wäre deutlicher erkennbar wenn man bei den Methoden 'einzahlen', 'auszahlen' und 'ueberweisung' nicht nur die Kontonummer ausgibt, sondern auch den Kontoinhaber.
Besser wäre wohl noch wenn die Methode 'ueberweisung' den Namen 'ueberweisen' hätte. Das passt dann besser zu 'einzahlen' und 'auszahlen'.
P.S. auch die Attribute einer Klasse sollten eigentlich klein geschrieben werden
Re: kleine Mathe-Spielereien
Verfasst: Mittwoch 25. Juni 2025, 16:25
von OSWALD
24.6.2025
@grubenfox danke für die guten Tips.
Ich bin selbst ganz verwirrt, weil ich zu viel Konten angesprochen habe, ohne besser zu kontrollieren. .
Neben der Kontonummer werde ich
auch die Inhaber anzeigen. Vielleicht schaffe ich auch noch die
Nullstellung aller Konten. Bevor ich den Polymorphismus angehen kann, muss ich noch Vieles klären.
'Nach update ist vor update' OSWALD
Re: kleine Mathe-Spielereien
Verfasst: Mittwoch 25. Juni 2025, 17:37
von Dennis89
Um das mal etwas detaillierter zu beschreiben.
`Konto` muss nicht von `object` erben. Die ".. Konto anlegen" Ausgabe gehört nicht in die `__init__` das ist Programmablauf und sollte in die `main`-Funktion, das gilt auch für den `zeige_konto`-Aufruf. Namen werden klein mit Unterstrich geschrieben, Ausnahmen sind Konstanten die GANZ_GROSS und Klassen in PascalCase-Schreibweise.
Wenn eine Methode `einzahlen` heißt, dann sind die Doc-Strings überflüssig und auch die Kommentare. Ich verstehe das "Achtung...." nicht. Das verwirrt mich eher, als das es mir hilft.
Strings kann man schön leserlich mit f-Strings formatieren.
Wieso verwendest du 2 führende Unterstriche? Einer zeigt dem Leser an dass man auf die Werte von außerhalb nicht zugreifen soll.
Ich sehe keinen begrabenen Hund, nur die gleiche Methode wie schon in der Eltern-Klasse, die kann also weg.
In `SparKonto` finde ich das Überschreiben von `zeige_konto` nicht schön, weil man es nur um den Zinssatz ergänzt, dabei kann man den auch einfach so abfragen.
Alles unter `if __name__ == __main__:` gehört in eine `main`-Funktion. Aus ihr wird üblicherweise der Programmablauf gesteuert.
Ich habe mal die ganzen Leerzeichen noch entfernt, ich weiß nicht wie es dir geht, aber mich macht das verrückt.
Code: Alles auswählen
class Konto:
def __init__(self, inhaber, kontonummer, kontostand):
self.inhaber = inhaber
self.kontonummer = kontonummer
self.kontostand = kontostand
def einzahlen(self, betrag):
print(f"..Einzahlen: {self.kontonummer} {betrag:.1f}")
self.kontostand += betrag
def auszahlen(self, betrag):
print(f"..Auszahlen: {self.kontonummer} {betrag:.1f}")
self.kontostand -= betrag
def ueberweisung(self, ziel, betrag):
print(f"..Transfer: {self.kontonummer} -> {ziel.kontonummer} {betrag:.1f}")
self.kontostand -= betrag
ziel.kontostand += betrag
def zeige_konto(self):
print("..Konto:", self.inhaber)
print("Kontonummer:", self.kontonummer)
print("Kontostand:", self.kontostand)
class GiroKonto(Konto):
def __init__(self, inhaber, kontonummer, kontostand, sollzinsen, habenzinsen):
self.sollzinsen = sollzinsen
self.habenzinsen = habenzinsen
Konto.__init__(self, inhaber, kontonummer, kontostand)
class SparKonto(Konto):
def __init__(self, inhaber, kontonummer, kontostand, zinssatz):
self.zinssatz = zinssatz
Konto.__init__(self, inhaber, kontonummer, kontostand)
def main():
print("Neues Konto erstellen")
oswald = GiroKonto("Oswald Meier", 78340, 120, 0.05, 0.01)
oswald.zeige_konto()
print()
klaus = SparKonto("Klaus Freund", 78300, 150, 0.05)
print("Jetzt Konten bearbeiten")
print("=Oswald Meier zahlt auf sein Girokonto ein:")
oswald.einzahlen(333333)
print("Klaus zahlt auf sein Sparkonto ein")
klaus.einzahlen(5555)
print("Oswald Meier zahlt aus von Sparkonto")
oswald.auszahlen(0)
print("Oswald Meier überweist von Giro - auf Sparkonto")
oswald.ueberweisung(klaus, 10000)
klaus.auszahlen(3000)
print()
print("GIRO aktueller Kontostand")
oswald.zeige_konto()
print("SPAR aktueller Kontostand")
klaus.zeige_konto()
print(f"Zinssatz: {klaus.zinssatz}")
print()
print("Jetzt Konten bearbeiten")
print()
print("Oswald zahlt auf sein Konto Nr.78340 ein")
oswald.einzahlen(3000)
print("Oswald zahlt von seinem Konto Nr.78340 aus")
oswald.auszahlen(400)
oswald.ueberweisung(klaus, 500)
print("Überweisung Klaus an Oswald")
klaus.ueberweisung(oswald, 468)
print()
print("GIRO ktueller Kontostand")
oswald.zeige_konto()
print("SPAR aktueller Kontostand")
klaus.zeige_konto()
print()
if __name__ == '__main__':
main()
Jetzt müsste man was sinnvolles mit den Vererbungen machen, den mit der Ausnahme vom anzeigen des Zinssatzes, könnte das alles ein `Konto` sein, denn das hat ja normal auch einen Zinssatz und dann wärst du wieder hier:
Code: Alles auswählen
class Konto:
def __init__(self, inhaber, kontonummer, kontostand, zinssatz=None):
self.inhaber = inhaber
self.kontonummer = kontonummer
self.kontostand = kontostand
self.zinssatz = zinssatz
def einzahlen(self, betrag):
print(f"..Einzahlen: {self.kontonummer} {betrag:.1f}")
self.kontostand += betrag
def auszahlen(self, betrag):
print(f"..Auszahlen: {self.kontonummer} {betrag:.1f}")
self.kontostand -= betrag
def ueberweisung(self, ziel, betrag):
print(f"..Transfer: {self.kontonummer} -> {ziel.kontonummer} {betrag:.1f}")
self.kontostand -= betrag
ziel.kontostand += betrag
def zeige_konto(self):
print("..Konto:", self.inhaber)
print("Kontonummer:", self.kontonummer)
print("Kontostand:", self.kontostand)
def main():
print("Neues Konto erstellen")
oswald = Konto("Oswald Meier", 78340, 120)
oswald.zeige_konto()
print()
klaus = Konto("Klaus Freund", 78300, 150, 0.05)
print("Jetzt Konten bearbeiten")
print("=Oswald Meier zahlt auf sein Girokonto ein:")
oswald.einzahlen(333333)
print("Klaus zahlt auf sein Sparkonto ein")
klaus.einzahlen(5555)
print("Oswald Meier zahlt aus von Sparkonto")
oswald.auszahlen(0)
print("Oswald Meier überweist von Giro - auf Sparkonto")
oswald.ueberweisung(klaus, 10000)
klaus.auszahlen(3000)
print()
print("GIRO aktueller Kontostand")
oswald.zeige_konto()
print("SPAR aktueller Kontostand")
klaus.zeige_konto()
print(f"Zinssatz: {klaus.zinssatz}")
print()
print("Jetzt Konten bearbeiten")
print()
print("Oswald zahlt auf sein Konto Nr.78340 ein")
oswald.einzahlen(3000)
print("Oswald zahlt von seinem Konto Nr.78340 aus")
oswald.auszahlen(400)
oswald.ueberweisung(klaus, 500)
print("Überweisung Klaus an Oswald")
klaus.ueberweisung(oswald, 468)
print()
print("GIRO ktueller Kontostand")
oswald.zeige_konto()
print("SPAR aktueller Kontostand")
klaus.zeige_konto()
print()
if __name__ == '__main__':
main()
Deine Ausgaben und die verwirrten und falschen Kontenangaben habe ich auch aufgeräumt. Schau es dir mal in Ruhe an. Ich hoffe das hilft etwas weiter.
Grüße
Dennis
Re: kleine Mathe-Spielereien
Verfasst: Donnerstag 26. Juni 2025, 07:47
von snafu
Man könnte die Basisfunktionalität für Geldbewegungen auch als transfer() abbilden, welcher Plus und Minus erlaubt und im Hintergrund jede Bewegung protokolliert. Spezialisierte Klassen würden dann konkrete Methoden implementieren. Von einem Sparkonto kann ich z. B. keine Überweisungen auf ein beliebiges Konto tätigen. Bei einem Wertpapierdepot habe ich ein Referenzkonto für die An- und Verkäufe und kann oft für eine Auszahlung an einer andere Bank nur ein vorab registriertes Konto benutzen. OOP kann da IMHO ziemlich gut benutzt werden, sobald man nicht mehr nur an der Oberfläche kratzt.
zeige_konto() ist übrigens eigentlich __str__(), nur dann eben als Rückgabe einer mit Newlines getrennten Zeichenkette. Die print()-Ausgaben innerhalb der Methoden würde ich nur fürs Debugging benutzen und später rausnehmen oder auskommentieren.
Re: kleine Mathe-Spielereien
Verfasst: Donnerstag 26. Juni 2025, 15:52
von OSWALD
26.6.25
Herzlichen Dank für die vielen Erläuterungen
und Tips, die ich alle umzusetzen versuche und z.T.
auch schon umsetzen konnte.
Allerdings habe ich festgestellt, dass ich quasi wieder ganz
von vorne beginnen muss.
Deshalb habe ich zunächst alles auf NULL gestellt, um
den Überblick nicht zu verlieren.
OSWALD
Code: Alles auswählen
class Konto(object):
""" Basis Konto Klasse """
def __init__(self, inhaber, kontonummer, kontostand):
""" Konstruktor, Aufruf bei Instanzierung """
print( ".. Konto anlegen")
self.Inhaber = inhaber
self.Kontonummer = kontonummer
self.Kontostand = kontostand
self.zeige_konto()
def einzahlen(self, betrag):
""" Mach eine Einzahlung """
print (".. Einzahlen : %i %5.1f" % (self.Kontonummer, betrag))
self.Kontostand += betrag
def auszahlen(self, betrag):
""" Mach eine Auszahlung """
print( ".. Auszahlen : %i %5.1f" % (self.Kontonummer, betrag))
self.Kontostand -= betrag
def ueberweisung(self, ziel, betrag):
""" Mach eine Ueberweisung """
print( ".. Transfer : %i %s %i %5.1f" % (self.Kontonummer, "->", ziel.Kontonummer, betrag))
self.Kontostand -= betrag
ziel.Kontostand += betrag
def zeige_konto(self):
""" Zeige die Kontodaten am Bildschirm """
print( ".. Konto :", self.Inhaber)
print( " Kontonummer :", self.Kontonummer)
print( " Kontostand :", self.Kontostand )
#############################
class Girokonto(Konto):
def __init__(self, inhaber, kontonummer, kontostand, sollzinsen, habenzinsen):
""" Giro Konstruktor, Aufruf Instanzierung """
self.__Sollzinsen = sollzinsen
self.__Habenzinsen = habenzinsen
# initialisiere Konto
Konto.__init__(self, inhaber, kontonummer, kontostand)
def ueberweisung(self, ziel, betrag):
""" Mach eine Ueberweisung """
print( ".. Transfer : %i %s %i %5.1f" % (self.Kontonummer, "->", ziel.Kontonummer, betrag))
self.Kontostand -= betrag
ziel.Kontostand += betrag
##############################
class Sparkonto(Konto):
""" Sparbuch Konto Klasse """
def __init__(self, inhaber, kontonummer, kontostand, zinssatz):
""" Spar Konstruktor, Aufruf bei Instanzierung """
self.Zinssatz = zinssatz
# initialisiere des Kontos
Konto.__init__(self, inhaber, kontonummer, kontostand)
def zeige_konto(self):
""" Zeige die Kontodaten am Bildschirm, ueberschreibt Konto Funktion """
Konto.zeige_konto(self)
print( (" Zinssatz :", self.Zinssatz ))
####################################################
# ALLE Konten auf NUKL gesetzt
if __name__ == '__main__':
print(" Neues Konto erstellen ")
kgiro = Girokonto(" Oswald Meier", 78340, 0.0, 0.0, 0.0)
kspar = Sparkonto("Oswald Meier", 78341, 0.0, 0.0)
print()
print(" GIRO ktueller Kontostand ")
print(kgiro.zeige_konto() )
print(" SPAR aktueller Kontostand ")
kspar.zeige_konto()
print()
kgiro = Girokonto("Klaus Freund",78200, 0.0, 0.0, 0.0)
kspar = Sparkonto("Klaus Freund",78300 ,0.0 , 0.00)
print("=========================================")
print( " Jetzt Konten bearbeiten")
kgiro.ueberweisung(kspar,0.0)
print("= Oswald Meier zahlt auf sein Girokonto ein :")
kgiro.einzahlen(0)
print(" Oswald Meier zahlt auf sein Sparkonto ein ")
kspar.einzahlen(0)
print(" Oswald Meier überweist von Giro - auf Sparkonto")
kgiro.ueberweisung(kspar, 0.0)
kspar.auszahlen (0.0)
print()
print(" Oswald Meier GIRO aktueller Kontostand ")
print(kgiro.zeige_konto() )
print(" SPAR aktueller Kontostand ")
kspar.zeige_konto()
print()
print("Klaus Freund zahlt auf sein Konto Nr.78300 ein")
kgiro.einzahlen( 0)
print("Klaus Freund zahlt von seinem Konto Nr.78200 aus")
kgiro.auszahlen (0)
kgiro.ueberweisung(kspar , 0.0)
print(" Klaus Freund GIRO aktueller Kontostand ")
kgiro.zeige_konto()
print(" SPAR aktueller Kontostand ")
kspar.zeige_konto()
print()
Re: kleine Mathe-Spielereien
Verfasst: Freitag 4. Juli 2025, 11:18
von OSWALD
4.7.2025Die objektorientierte Programmierung (OOP) basiert auf vier Hauptprinzipien:
Kapselung, Vererbung, Polymorphismus und Abstraktion.
Diese Prinzipien ermöglichen es, Code wieder verwendbar, flexibel und wartbar zu gestalten.
Ich habe mich intensiv mit Vererbung und Polymorphismus beschäftigt und versucht
die komplexe Materie ein bisschen besser zu verstehen.
Kapselung und Abstraktion folgen später.
Dazu kam mir ein Programm gelegen, das ich hier vorstellen will:
Auf den ersten Blick nicht gerade aufregend, aber nach und nach
zeigte sich , dass es eine Menge über OOP bietet.
Es hat sich gelohnt.
Gute Zeit OSWALD
Code: Alles auswählen
class Container:
def __init__(self, volume):
# volume in ml
self._volume = volume
# start out with empty container
self._contents = {}
def __repr__(self):
"""
Textual representation of container
"""
repr = f"{self._volume} ml Container with contents {self._contents}"
return repr
def volume(self):
"""
Volume getter
"""
return self._volume
def is_empty(self):
"""
Container is empty if it has no contents
"""
return self._contents == {}
def is_full(self):
"""
Container is full if volume of contents equals capacity
"""
return self.volume_filled() == self.volume()
def volume_filled(self):
"""
Calculate sum of volumes of contents
"""
return sum(self._contents.values())
def volume_available(self):
"""
Calculate available volume
"""
return self.volume() - self.volume_filled()
def empty(self):
"""
Empty the container, returning its contents
"""
contents = self._contents.copy()
self._contents.clear()
return contents
def _add(self, substance, volume):
"""
Internal method to add a new substance / add more of an existing substance
"""
# update volume of existing substance
if substance in self._contents:
self._contents[substance] += volume
# or add new substance
else:
self._contents[substance] = volume
def add(self, substance, volume):
"""
Public method to add a substance, possibly returning left over
"""
if self.is_full():
raise Exception("Cannot add to full container")
# we can fit all of the substance
if self.volume_filled() + volume <= self.volume():
self._add(substance, volume)
return self
# we can fit part of the substance, returning the left over
else:
leftover = volume - self.volume_available()
self._add(substance, volume - leftover)
return {substance: leftover}
def fill(self, substance):
"""
Fill the container with a substance
"""
if self.is_full():
raise Exception("Cannot fill full container")
self._add(substance, self.volume_available())
return self
def pour_into(self, other_container):
"""
Transfer contents of container to another container
"""
if other_container.volume_available() < self.volume_filled():
raise Exception("Not enough space")
# get the contents by emptying container
contents = self.empty()
# add contents to other container
for substance, volume in contents.items():
other_container.add(substance, volume)
return other_container
def __add__(self, other_container):
"""
Implement addition for containers:
`container_a + container_b` <=> `container_b.pour_into(container_a)`
"""
other_container.pour_into(self)
return self
glass = Container(300)
glass.fill('Water')
assert glass.is_full()
contents = glass.empty()
assert contents == {'Water': 300}
assert glass.is_empty()
pitcher = Container(1500)
bottle = Container(700)
carton = Container(500)
# fill ingredients
bottle.fill('Red wine')
carton.fill('Orange juice')
# pour ingredients into pitcher
pitcher += bottle # pitcher ist Krig zum Ausschenken
pitcher += carton
# check that everything worked
assert pitcher.volume_filled() == 1200
assert bottle.is_empty() and carton.is_empty()
#Vererbung
class Sealable:
"""
Implementation needs to:
- initialize `self._seal`
"""
def is_sealed(self):
return self._seal is not None
def is_open(self):
return not self.is_sealed()
def is_closed(self):
return not self.is_open()
def open(self):
"""
Opening removes and returns the seal
"""
seal = self._seal
self._seal = None
return seal
def seal_with(self, seal):
"""
Closing attaches the seal and returns the Sealable
"""
self._seal = seal
return self
class SealableContainer(Container, Sealable):
"""
Start out with empty, open container
"""
def __init__(self, volume, contents = {}, seal = None):
# initialize `Container`
super().__init__(volume)
# initialize contents
self._contents = contents
# initialize `self._seal`
self._seal = seal
def __repr__(self):
"""
Append 'open' / 'closed' to textual container representation
"""
state = "Open" if self.is_open() else "Closed"
repr = f"{state} {super().__repr__()}"
return repr
def empty(self):
"""
Only open container can be emptied
"""
if self.is_open():
return super().empty()
else:
raise Exception("Cannot empty sealed container")
def _add(self, substance, volume):
"""
Only open container can have its contents modified
"""
if self.is_open():
super()._add(substance, volume)
else:
super()._add(substance, volume+volume)
glass = Container(530)
cola_bottle = SealableContainer(530, contents = {'Cola': 250}, seal = 'Bottlecap') # ='Kron-verschluss'
shot_glass = Container(140)
shot_glass.add('Rum', 20)
shot_glass.add('Sirup',50)
shot_glass.add('Gin',30)
shot_glass.add('Eis',100)
# Wir geben etwas Eis in da Glas und fügen den Rum hinzu.
# Da die Cola-Flasche verschlossen ist, öffnen wir sie zunächst und gießen dann den Inhalt in das Glas:
glass.add('Ice', 50)
# add rum
glass += shot_glass
# open cola bottle
if cola_bottle.is_closed():
cola_bottle.open()
# pour cola into glass
glass += cola_bottle
print(glass)
Re: kleine Mathe-Spielereien
Verfasst: Freitag 4. Juli 2025, 14:03
von OSWALD
r 4.7.2025
Und hier noch zwei prägnante Beispiele für
Polymorphismus
OSWALD
Code: Alles auswählen
lass TestPolymorphismus:
def add(self,a,b,c=None):
if c ==None:
sum = a+b
return sum
else:
sum = a+b+c
return sum
obj = TestPolymorphismus()
print(obj.add(1,2))
print(obj.add(1,2,3))
#####################
class Vektor:
""" 2D Vektor Klasse """
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
""" Ueberladener '+' Operator """
return Vektor( self.x+other.x, self.y+other.y )
def __str__(self):
""" Ueberladene print Funktion """
return f"[{self.x} {self.y}]"
if __name__ == '__main__':
print("\nBeispiel Polymorphismus")
# Erzeuge zwei Vektor Objekte
v1 = Vektor(3,4)
v2 = Vektor(1,2)
v3 = Vektor(7,10)
# Addiere 2 Vektoren
vs = v1 + v2
# Ausgabe des neuen Vektors
print('vs =', vs)
print(v3)
Re: kleine Mathe-Spielereien
Verfasst: Freitag 4. Juli 2025, 14:31
von __blackjack__
@OSWALD: Was genau ist denn da jetzt der Polymorphismus? Gezeigt wird da nicht wirklich etwas.
Wobei das erste Beispiel ja nicht mal ein Beispiel für eine Klasse ist, denn ein Objekt ohne Zustand mit nur einer “Methode“ ist einfach nur eine recht umständlich geschriebene Funktion.
Edit: 1. Beispiel ohne ”Klasse”:
Code: Alles auswählen
def add(a, b, c=None):
return a + b if c is None else a + b + c
print(add(1, 2))
print(add(1, 2, 3))
Re: kleine Mathe-Spielereien
Verfasst: Freitag 4. Juli 2025, 16:10
von OSWALD
4.7.2025
@ blackjack
Ich habe deshalb die beiden Programmbeispiele gegenüber gestellt.
Und schon taucht das nächste Problem auf.
----Unterschied Vererbung und Komposition von Klassen -----
Ich darf mich nur nicht entmutigen lassen.Ich dafür ch ein Programmbeispiel,
muss das aber noch verstehen. Auf jeden Fall spannend.
OSWALD
Re: kleine Mathe-Spielereien
Verfasst: Sonntag 6. Juli 2025, 09:36
von OSWALD
6.7.2025
Mit dem folgenden Programm glaube ich endgültig
die beste Erklärung für den Begriff 'Polymorphismus'
gefunden und auch verstanden zu haben.
Hier ist der Code.
Gute Zeit OSWALD
Code: Alles auswählen
class Car:
def __init__(self, brand, model):
self.brand = brand
self.model = model
def move(self):
print("Drive!")
class Boat:
def __init__(self, brand, model):
self.brand = brand
self.model = model
def move(self):
print("Sail!")
class Plane:
def __init__(self, brand, model):
self.brand = brand
self.model = model
def move(self):
print("Fly!")
car1 = Car("Ford", "Mustang") #Create a Car object
boat1 = Boat("Ibiza", "Touring 20") #Create a Boat object
plane1 = Plane("Boeing", "747") #Create a Plane object
for x in (car1, boat1, plane1):
x.move()
Re: kleine Mathe-Spielereien
Verfasst: Sonntag 6. Juli 2025, 09:56
von snafu
Wobei genau an der Stelle Vererbung sinnvoll wäre. Unter Nutzung vernünftiger Namen und anderer PEP8-Richtlinien könnte dein Code dann so aussehen:
Code: Alles auswählen
#!/usr/bin/env python3
class Vehicle:
def __init__(self, brand, model):
self.brand = brand
self.model = model
def move(self):
print("Move!")
class Car(Vehicle):
def move(self):
print("Drive!")
class Boat(Vehicle):
def move(self):
print("Sail!")
class Plane(Vehicle):
def move(self):
print("Fly!")
def main():
car = Car("Ford", "Mustang")
boat = Boat("Ibiza", "Touring 20")
plane = Plane("Boeing", "747")
for vehicle in car, boat, plane:
vehicle.move()
if __name__ == "__main__":
main()
Der Polymorphismus besteht darin, dass ich alle Objekte wie ein Vehicle behandeln kann, denn sie haben die gleiche Schnittstelle. Aber durch die spezifischen Implementierungen wird ein unterschiedliches Verhalten erreicht.
Funktioniert übrigens auch mit ``dataclass``:
Code: Alles auswählen
#!/usr/bin/env python3
from dataclasses import dataclass
@dataclass
class Vehicle:
brand: str
model: str
def move(self):
print("Move!")
class Car(Vehicle):
def move(self):
print("Drive!")
class Boat(Vehicle):
def move(self):
print("Sail!")
class Plane(Vehicle):
def move(self):
print("Fly!")
def main():
car = Car("Ford", "Mustang")
boat = Boat("Ibiza", "Touring 20")
plane = Plane("Boeing", "747")
for vehicle in car, boat, plane:
print(vehicle)
vehicle.move()
if __name__ == "__main__":
main()
Re: kleine Mathe-Spielereien
Verfasst: Sonntag 6. Juli 2025, 10:25
von OSWALD
6.7.25
@snafu
Danke für das schöne Beispiel.
Genau aus dem genannten Grund ist es für
Anfänger so schwer mit OOP klar zu kommen.
Ich zeige hier hier ein analoges Beispiel, über das ich
ehrlicherweise lange nachdenken musste.
OSWALD
Code: Alles auswählen
# Unterschied zwischen Instanzvariable u Klassenvariable.(wird für OOP nicht empfohelen )
class Wall():
def __init__(self):
self.height = 10 #Instanzvariable
south_wall = Wall()
south_wall.height = 20 # updates only this instance of a wall
print(south_wall.height)
# prints "20"
north_wall = Wall()
print(north_wall.height)
# prints "10"
print()
#########
class Wall():
height = 10 # Klassenvariable
south_wall = Wall()
print(south_wall.height)
# prints "10"
Wall.height = 20 # updates all instances of a Wall
print(south_wall.height)
# prints "20"