Rheinwerk Computing < openbook >

 
Inhaltsverzeichnis
1 Einleitung
2 Die Programmiersprache Python
Teil I Einstieg in Python
3 Erste Schritte im interaktiven Modus
4 Der Weg zum ersten Programm
5 Kontrollstrukturen
6 Dateien
7 Das Laufzeitmodell
8 Funktionen, Methoden und Attribute
9 Informationsquellen zu Python
Teil II Datentypen
10 Das Nichts – NoneType
11 Operatoren
12 Numerische Datentypen
13 Sequenzielle Datentypen
14 Zuordnungen
15 Mengen
16 Collections
17 Datum und Zeit
18 Aufzählungstypen – Enum
Teil III Fortgeschrittene Programmiertechniken
19 Funktionen
20 Modularisierung
21 Objektorientierung
22 Ausnahmebehandlung
23 Iteratoren
24 Kontextobjekte
25 Manipulation von Funktionen und Methoden
Teil IV Die Standardbibliothek
26 Mathematik
27 Kryptografie
28 Reguläre Ausdrücke
29 Schnittstelle zu Betriebssystem und Laufzeitumgebung
30 Kommandozeilenparameter
31 Dateisystem
32 Parallele Programmierung
33 Datenspeicherung
34 Netzwerkkommunikation
35 Debugging und Qualitätssicherung
36 Dokumentation
Teil V Weiterführende Themen
37 Anbindung an andere Programmiersprachen
38 Distribution von Python-Projekten
39 Grafische Benutzeroberflächen
40 Python als serverseitige Programmiersprache im WWW – ein Einstieg in Django
41 Wissenschaftliches Rechnen
42 Insiderwissen
43 Von Python 2 nach Python 3
A Anhang
Stichwortverzeichnis

Download:
- Beispielprogramme, ca. 464 KB

Jetzt Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Python 3 von Johannes Ernesti, Peter Kaiser
Das umfassende Handbuch
Buch: Python 3

Python 3
Pfeil 21 Objektorientierung
Pfeil 21.1 Klassen
Pfeil 21.1.1 Definieren von Methoden
Pfeil 21.1.2 Der Konstruktor und die Erzeugung von Attributen
Pfeil 21.2 Vererbung
Pfeil 21.2.1 Technische Grundlagen
Pfeil 21.2.2 Die Klasse GirokontoMitTagesumsatz
Pfeil 21.2.3 Mögliche Erweiterungen der Klasse Konto
Pfeil 21.2.4 Ausblick
Pfeil 21.2.5 Mehrfachvererbung
Pfeil 21.3 Setter und Getter und Property Attributes
Pfeil 21.3.1 Setter und Getter
Pfeil 21.3.2 Property-Attribute
Pfeil 21.4 Klassenattribute und Klassenmethoden sowie statische Methoden
Pfeil 21.4.1 Statische Methoden
Pfeil 21.4.2 Klassenmethoden
Pfeil 21.4.3 Klassenattribute
Pfeil 21.5 Built-in Functions für Objektorientierung
Pfeil 21.5.1 Funktionen für die Verwaltung der Attribute einer Instanz
Pfeil 21.5.2 Funktionen für Informationen über die Klassenhierarchie
Pfeil 21.6 Objektphilosophie
Pfeil 21.7 Magic Methods und Magic Attributes
Pfeil 21.7.1 Allgemeine Magic Methods
Pfeil 21.7.2 Operatoren überladen
Pfeil 21.7.3 Datentypen emulieren
 
Zum Seitenanfang

21    Objektorientierung Zur vorigen ÜberschriftZur nächsten Überschrift

In diesem Kapitel lassen wir endlich die Katze aus dem Sack: Sie werden in das wichtigste und grundlegendste Konzept von Python eingeführt, die Objektorientierung. Der Begriff Objektorientierung beschreibt ein Programmierparadigma, mit dem die Konsistenz von Datenobjekten gesichert werden kann und das die Wiederverwendbarkeit von Quellcode verbessert. Diese Vorteile werden dadurch erreicht, dass man Datenstrukturen und die dazugehörigen Operationen zu einem Objekt zusammenfasst und den Zugriff auf diese Strukturen nur über bestimmte Schnittstellen erlaubt.

Diese Vorgehensweise werden wir an einem Beispiel veranschaulichen, indem wir zuerst auf dem bisherigen Weg eine Lösung erarbeiten und diese dann ein zweites Mal, diesmal aber unter Verwendung der objektorientierten Mechanismen von Python, implementieren.

Stellen Sie sich vor, wir würden für eine Bank ein System für die Verwaltung von Konten entwickeln, das das Anlegen neuer Konten, Überweisungen sowie Ein- und Auszahlungen regelt. Ein möglicher Ansatz wäre, dass Sie für jedes Bankkonto ein Dictionary anlegen, in dem alle Informationen über den Kunden und seinen Finanzstatus gespeichert sind. Um die gewünschten Operationen zu unterstützen, definieren Sie Funktionen. Ein Dictionary für ein vereinfachtes Konto sieht dann folgendermaßen aus:[ 85 ](Wir verwenden hier float-Instanzen zum Speichern von Geldbeträgen, um die Beispiele einfach zu halten. Mit diesem Datentyp können bei sehr großen Beträgen Informationen verloren gehen. Deshalb sollten Sie bei Bankanwendungen eine exakte Repräsentation der Beträge, z. B. mithilfe des Typs decimal.Decimal, siehe Abschnitt 26.3, »Abschnitt 26.3«, wählen. )

konto = {
"Inhaber" : "Hans Meier",
"Kontonummer" : 567123,
"Kontostand" : 12350.0,
"MaxTagesumsatz" : 1500,
"UmsatzHeute" : 10.0
}

Wir gehen modellhaft davon aus, dass jedes Konto einen "Inhaber" hat, der durch einen String mit seinem Namen identifiziert wird. Das Konto hat eine ganzzahlige "Kontonummer", um es von allen anderen Konten zu unterscheiden. Mit der Gleitkommazahl, die mit dem Schlüssel "Kontostand" verknüpft ist, wird das aktuelle Guthaben in Euro gespeichert. Die Schlüssel "MaxTagesumsatz" und "UmsatzHeute" dienen dazu, den Tagesumsatz eines jeden Kunden zu seinem eigenen Schutz auf ein bestimmtes Limit zu begrenzen. "MaxTagesumsatz" gibt dabei an, wie viel Geld pro Tag maximal von dem bzw. auf das Konto bewegt werden darf. Mit "UmsatzHeute" »merkt« sich das System, wie viel am heutigen Tag schon umgesetzt worden ist. Zu Beginn eines neuen Tages wird dieser Wert wieder auf null gesetzt.

Ausgehend von dieser Datenstruktur werden wir nun die geforderten Operationen als Funktionen definieren. Als Erstes brauchen wir eine Funktion, die ein neues Konto nach bestimmten Vorgaben erzeugt:

def neues_konto(inhaber, kontonummer, kontostand, max_tagesumsatz=1500):
return {
"Inhaber" : inhaber,
"Kontonummer" : kontonummer,
"Kontostand" : kontostand,
"MaxTagesumsatz" : max_tagesumsatz,
"UmsatzHeute" : 0
}

An einem Geldtransfer sind immer ein Sender (das Quellkonto) und ein Empfänger (das Zielkonto) beteiligt. Außerdem muss zur Durchführung der Überweisung der gewünschte Geldbetrag bekannt sein. Die Funktion wird also drei Parameter erwarten: quelle, ziel und betrag. Nach unseren Voraussetzungen ist eine Überweisung nur dann möglich, wenn die Tagesumsätze der beiden Konten ihr Limit nicht überschreiten. Die Überweisungsfunktion soll einen Wahrheitswert zurückgeben, der angibt, ob die Überweisung ausgeführt werden konnte oder nicht. Damit lässt sie sich folgendermaßen implementieren:

def geldtransfer(quelle, ziel, betrag):
# Hier erfolgt der Test, ob der Transfer möglich ist
if(betrag < 0 or
quelle["UmsatzHeute"] + betrag > quelle["MaxTagesumsatz"] or
ziel["UmsatzHeute"] + betrag > ziel["MaxTagesumsatz"]):
# Transfer unmöglich
return False
else:
# Alles OK - Auf geht's
quelle["Kontostand"] -= betrag
quelle["UmsatzHeute"] += betrag
ziel["Kontostand"] += betrag
ziel["UmsatzHeute"] += betrag
return True

Die Funktion überprüft zuerst, ob der Transfer durchführbar ist, und beendet den Funktionsaufruf frühzeitig mit dem Rückgabewert False, wenn dies nicht der Fall ist. Wenn für den Betrag ein gültiger Wert übergeben wurde und kein Tagesumsatzlimit überschritten wird, aktualisiert die Funktion Kontostände und Tagesumsätze entsprechend der Überweisung und gibt True zurück.

Die letzten Operationen für unsere Modellkonten sind das Ein- beziehungsweise Auszahlen am Geldautomaten oder Bankschalter. Beide Funktionen benötigen als Parameter das betreffende Konto und den jeweiligen Geldbetrag.

def einzahlen(konto, betrag):
if betrag < 0 or konto["UmsatzHeute"] + betrag > konto["MaxTagesumsatz"]:
# Tageslimit überschritten oder ungültiger Betrag
return False
else:
konto["Kontostand"] += betrag
konto["UmsatzHeute"] += betrag
return True

def auszahlen(konto, betrag):
if betrag < 0 or konto["UmsatzHeute"] + betrag > konto["MaxTagesumsatz"]:
# Tageslimit überschritten oder ungültiger Betrag
return False
else:
konto["Kontostand"] -= betrag
konto["UmsatzHeute"] += betrag
return True

Auch diese Funktionen geben, abhängig von ihrem Erfolg, einen Wahrheitswert zurück.

Um einen Überblick über den aktuellen Status unserer Konten zu erhalten, definieren wir eine einfache Ausgabefunktion:

def zeige_konto(konto):
print("Konto von {}".format(konto["Inhaber"]))
print("Aktueller Kontostand: {:.2f} Euro".format(konto["Kontostand"]))
print("(Heute schon {:.2f} von {} Euro umgesetzt)".format(
konto["UmsatzHeute"], konto["MaxTagesumsatz"]))

Mit diesen Definitionen könnten wir beispielsweise folgende Bankoperationen simulieren:

>>> k1 = neues_konto("Heinz Meier", 567123, 12350.0)
>>> k2 = neues_konto("Erwin Schmidt", 396754, 15000.0)
>>> geldtransfer(k1, k2, 160)
True
>>> geldtransfer(k2, k1, 1000)
True
>>> geldtransfer(k2, k1, 500)
False
>>> einzahlen(k2, 500)
False
>>> zeige_konto(k1)
Konto von Heinz Meier
Aktueller Kontostand: 13190.00 Euro
(Heute schon 1160.00 von 1500 Euro umgesetzt)
>>> zeige_konto(k2)
Konto von Erwin Schmidt
Aktueller Kontostand: 14160.00 Euro
(Heute schon 1160.00 von 1500 Euro umgesetzt)

Zuerst eröffnet Heinz Meier ein neues Konto k1 mit der Kontonummer 567123 und mit einem Startguthaben von 12.350 Euro. Erwin Schmidt zahlt 15.000 Euro auf sein neues Konto k2 mit der Kontonummer 396754 ein. Beide haben den standardmäßigen maximalen Tagesumsatz von 1.500 Euro gewählt. Nun treten die beiden in geschäftlichen Kontakt miteinander, wobei Herr Meier von Herrn Schmidt einen DVD-Rekorder für 160 Euro kauft und diesen per Überweisung bezahlt. Am selben Tag erwirbt Herr Meier Herrn Schmidts gebrauchten Spitzenlaptop, der für 1.000 Euro den Besitzer wechselt. Als Herr Schmidt in den Abendstunden stark an der Heimkinoanlage von Herrn Meier interessiert ist und ihm dafür 500 Euro überweisen möchte, wird er enttäuscht, denn die Überweisung schlägt fehl. Völlig verdattert zieht Herr Schmidt den voreiligen Schluss, er habe zu wenig Geld auf seinem Konto. Deshalb möchte er den Betrag auf sein Konto einzahlen und anschließend erneut überweisen. Als aber auch die Einzahlung abgelehnt wird, wendet er sich an einen Bankangestellten. Dieser lässt sich die Informationen der beteiligten Konten anzeigen. Dabei sieht er, dass die gewünschte Überweisung das Tageslimit von Herrn Schmidts Konto überschreitet und deshalb nicht ausgeführt werden kann.

Wie Sie sehen, arbeitet unsere Banksimulation wie erwartet und ermöglicht uns eine relativ einfache Handhabung von Kontodaten. Sie weist aber eine unschöne Eigenheit auf, die wir im Folgenden besprechen werden.

In dem Beispiel sind die Datenstruktur und die Funktionen für ihre Verarbeitung getrennt definiert, was dazu führt, dass das Konto-Dictionary bei jedem Funktionsaufruf als Parameter übergeben werden muss.

Man kann sich aber auf den Standpunkt stellen, dass ein Konto nur mit den dazugehörigen Verwaltungsfunktionen sinnvoll benutzt werden kann und auch umgekehrt die Verwaltungsfunktionen eines Kontos nur in Zusammenhang mit dem Konto nützlich sind.

Genau diese Wünsche befriedigt die Objektorientierung, indem sie Daten und Verarbeitungsfunktionen zu Objekten zusammenfasst. Dabei werden die Daten eines solchen Objekts Attribute und die Verarbeitungsfunktionen Methoden genannt. Attribute und Methoden werden unter dem Begriff Member einer Klasse zusammengefasst. Schematisch lässt sich das Objekt eines Kontos also folgendermaßen darstellen:

Konto
Attribute Methoden
Inhaber
Kontostand
MaxTagesumsatz
UmsatzHeute
neues_konto()
geldtransfer()
einzahlen()
auszahlen()
zeige()

Tabelle 21.1    Schema eines Kontoobjekts

Die Begriffe »Attribut« und »Methode« sind Ihnen bereits aus früheren Kapiteln von den Basisdatentypen bekannt, denn jede Instanz eines Basisdatentyps stellt – auch wenn Sie es zu dem Zeitpunkt vielleicht noch nicht wussten – ein Objekt dar. Sie wissen auch schon, dass Sie auf die Attribute und Methoden eines Objekts zugreifen, indem Sie die Referenz auf das Objekt und das dazugehörige Member durch einen Punkt getrennt aufschreiben.

Angenommen, k1 und k2 sind Kontoobjekte, wie sie das oben dargestellte Schema zeigt, mit den Daten von Herrn Meier und Herrn Schmidt; dann können wir das letzte Beispiel folgendermaßen formulieren:[ 86 ](Der Code ist so natürlich noch nicht lauffähig, da die Definition für die Kontoobjekte fehlt, die erst im Folgenden erarbeitet wird. )

>>> k1.geldtransfer(k2, 160)
True
>>> k2.geldtransfer(k1, 1000)
True
>>> k2.geldtransfer(k1, 500)
False
>>> k2.einzahlen(500)
False
>>> k1.zeige()
Konto von Heinz Meier
Aktueller Kontostand: 13190.00 Euro
(Heute schon 1160.00 von 1500 Euro umgesetzt)
>>> k2.zeige()
Konto von Erwin Schmidt
Aktueller Kontostand: 14160.00 Euro
(Heute schon 1160.00 von 1500 Euro umgesetzt)

Die Methoden geldtransfer und zeige haben nun beim Aufruf einen Parameter weniger, da das Konto, auf das sie sich jeweils beziehen, jetzt am Anfang des Aufrufs steht. Da sich die Methode zeige nun automatisch auf ein Konto bezieht, haben wir den Namen der Methode entsprechend verkürzt.

Seit der Einführung der Basisdatentypen sind Sie bereits mit dem Umgang von Objekten und der Verwendung ihrer Attribute und Methoden vertraut. In diesem Kapitel werden Sie lernen, wie Sie Ihre eigenen Objekte mithilfe von Klassen erzeugen können.

 
Zum Seitenanfang

21.1    Klassen Zur vorigen ÜberschriftZur nächsten Überschrift

Objekte werden über Klassen erzeugt. Eine Klasse ist dabei eine formale Beschreibung der Struktur eines Objekts, die besagt, welche Attribute und Methoden es besitzt.

Mit einer Klasse allein kann man noch nicht sinnvoll arbeiten, da sie nur die Beschreibung eines Objekttyps darstellt, selbst aber kein Objekt ist.[ 87 ](Streng genommen sind in Python auch Klassen Instanzen sogenannter Metaklassen. Dies soll hier aber keine Rolle spielen. ) Man kann das Verhältnis von Klasse und Objekt mit dem von Backrezept und Kuchen vergleichen: Das Rezept definiert die Zutaten und den Herstellungsprozess eines Kuchens und damit auch seine Eigenschaften. Trotzdem reicht ein Rezept allein nicht aus, um die Verwandten zu einer leckeren Torte am Sonntagnachmittag einzuladen. Erst beim Backen wird aus der abstrakten Beschreibung ein fertiger Kuchen.

Ein anderer Name für ein Objekt ist Instanz. Das objektorientierte Backen wird daher Instanziieren genannt. So, wie es zu einem Rezept mehrere Kuchen geben kann, können auch mehrere Instanzen einer Klasse erzeugt werden:

Analogie von Rezept/Kuchen und Klasse/Objekt

Abbildung 21.1    Analogie von Rezept/Kuchen und Klasse/Objekt

Zur Definition einer neuen Klasse in Python dient das Schlüsselwort class, dem der Name der neuen Klasse folgt. Die einfachste Klasse hat weder Methoden noch Attribute und wird folgendermaßen definiert:

class Konto:
pass

Wie bereits gesagt, lässt sich mit einer Klasse allein nicht arbeiten, weil sie nur eine abstrakte Beschreibung ist. Deshalb wollen wir nun eine Instanz der noch leeren Beispielklasse Konto erzeugen. Um eine Klasse zu instanziieren, rufen Sie die Klasse wie eine Funktion ohne Parameter auf, indem Sie dem Klassennamen ein rundes Klammernpaar nachstellen. Der Rückgabewert dieses Aufrufs ist eine neue Instanz der Klasse:

>>> Konto()
<__main__.Konto object at 0x7f118556de10>

Die Ausgabe teilt uns mit, dass der Rückgabewert von Konto() eine Instanz der Klasse Konto im Namensraum __main__ ist und im Speicher unter der Adresse 0xb787776c abgelegt wurde – uns reicht als Information aus, dass eine neue Instanz der Klasse Konto erzeugt worden ist.

 
Zum Seitenanfang

21.1.1    Definieren von Methoden Zur vorigen ÜberschriftZur nächsten Überschrift

Im Prinzip unterscheidet sich eine Methode nur durch zwei Aspekte von einer Funktion: Erstens wird sie innerhalb eines von class eingeleiteten Blocks definiert, und zweitens erhält sie als ersten Parameter immer eine Referenz auf die Instanz, über die sie aufgerufen wird. Dieser erste Parameter muss nur bei der Definition explizit hingeschrieben werden und wird beim Aufruf der Methode automatisch mit der entsprechenden Instanz verknüpft. Da sich die Referenz auf das Objekt selbst bezieht, gibt man dem ersten Parameter den Namen self (dt. »selbst«). Methoden besitzen genau wie Funktionen einen eigenen Namensraum, können auf globale Variablen zugreifen und Werte per return an die aufrufende Ebene zurückgeben.

Damit können wir unsere Kontoklasse um die noch fehlenden Methoden ergänzen, wobei wir zunächst nur die Methodenköpfe ohne den enthaltenen Code aufschreiben:

class Konto:
def geldtransfer(self, ziel, betrag):
pass
def einzahlen(self, betrag):
pass
def auszahlen(self, betrag):
pass
def zeige(self):
pass

Beachten Sie den Parameter self am Anfang der Parameterliste jeder Methode, für den automatisch eine Referenz auf die Instanz übergeben wird, die beim Aufruf auf der linken Seite des Punktes steht:

>>> k = Konto()
>>> k.einzahlen(500)

Hier wird an die Methode einzahlen eine Referenz auf das Konto k übergeben, auf das dann innerhalb von einzahlen über den Parameter self zugegriffen werden kann.

Im nächsten Abschnitt werden Sie lernen, wie Sie in den Erzeugungsprozess neuer Objekte eingreifen und neue Attribute anlegen können.

 
Zum Seitenanfang

21.1.2    Der Konstruktor und die Erzeugung von Attributen Zur vorigen ÜberschriftZur nächsten Überschrift

Der Lebenszyklus jeder Instanz sieht gleich aus: Sie wird erzeugt, benutzt und anschließend wieder beseitigt. Dabei ist die Klasse, also der Bauplan, dafür verantwortlich, dass sich die Instanz zu jeder Zeit in einem wohldefinierten Zustand befindet. Aus diesem Grund gibt es eine spezielle Methode, die automatisch beim Instanziieren eines Objekts aufgerufen wird, um das Objekt in einen gültigen Initialzustand zu versetzen. Man nennt diese Methode den Konstruktor einer Klasse.

Um einer Klasse einen Konstruktor zu geben, müssen Sie eine Methode mit dem Namen[ 88 ](Dabei ist das Wort »init« sowohl von links als auch von rechts mit zwei Unterstrichen »_« umgeben. Methoden, die nach dem Schema __WORT__ aufgebaut sind, haben in Python eine besondere Bedeutung. Wir werden später in Abschnitt 21.7, »Abschnitt 21.7«, ausführlicher darauf eingehen. ) __init__ definieren.

class Beispielklasse:
def __init__(self):
print("Hier spricht der Konstruktor")

Wenn wir jetzt eine Instanz der Klasse Beispielklasse erzeugen, wird implizit die Methode __init__ aufgerufen, und der Text »Hier spricht der Konstruktor« erscheint auf dem Bildschirm:

>>> Beispielklasse()
Hier spricht der Konstruktor
<__main__.Beispielklasse object at 0x7f118556dfd0>

Konstruktoren können sinnvollerweise keine Rückgabewerte haben, da sie nicht direkt aufgerufen werden und beim Erstellen einer neuen Instanz schon eine Referenz auf die neue Instanz zurückgegeben wird.

[»]  Hinweis

Falls Sie bereits andere objektorientierte Programmiersprachen beherrschen und sich fragen, wie Sie in Python einen Destruktor implementieren können, sei Ihnen an dieser Stelle gesagt, dass es in Python keinen Destruktor gibt, der garantiert am Ende der Lebenszeit einer Instanz gerufen wird.

Ein ähnliches Verhalten kann mithilfe der Methode __del__ realisiert werden, die in Abschnitt 21.7.1 beschrieben wird.

Neue Attribute anlegen

Da es die Hauptaufgabe eines Konstruktors ist, einen konsistenten Initialzustand der Instanz herzustellen, sollten alle Attribute einer Klasse auch dort definiert werden.[ 89 ](Es gibt wenige Sonderfälle, in denen von dieser Regel abgewichen werden muss. Sie sollten im Regelfall alle Attribute Ihrer Klassen im Konstruktor anlegen. ) Die Definition neuer Attribute erfolgt durch eine Wertezuweisung, wie Sie sie von normalen Variablen kennen. Damit können wir die Funktion neues_konto durch den Konstruktor der Klasse Konto ersetzen, der dann wie folgt implementiert werden kann:

class Konto:
def __init__(self, inhaber, kontonummer, kontostand,
max_tagesumsatz=1500):
self.Inhaber = inhaber
self.Kontonummer = kontonummer
self.Kontostand = kontostand
self.MaxTagesumsatz = max_tagesumsatz
self.UmsatzHeute = 0
# hier kommen die restlichen Methoden hin

Da self eine Referenz auf die zu erstellende Instanz enthält, können wir über sie die neuen Attribute anlegen, wie das Beispiel zeigt. Auf dieser Basis können auch die anderen Funktionen der nicht objektorientierten Variante auf die Kontoklasse übertragen werden.

Im folgenden Listing sehen Sie die vollständige Klasse Konto.

class Konto:
def __init__(self, inhaber, kontonummer, kontostand,
max_tagesumsatz=1500):
self.Inhaber = inhaber
self.Kontonummer = kontonummer
self.Kontostand = kontostand
self.MaxTagesumsatz = max_tagesumsatz
self.UmsatzHeute = 0
def geldtransfer(self, ziel, betrag):
# Hier erfolgt der Test, ob der Transfer möglich ist
if (betrag < 0 or
self.UmsatzHeute + betrag > self.MaxTagesumsatz or
ziel.UmsatzHeute + betrag > ziel.MaxTagesumsatz):
# Transfer unmöglich
return False
else:
# Alles OK - Auf geht's
self.Kontostand -= betrag
self.UmsatzHeute += betrag
ziel.Kontostand += betrag
ziel.UmsatzHeute += betrag
return True
def einzahlen(self, betrag):
if betrag < 0 or self.UmsatzHeute + betrag > self.MaxTagesumsatz:
# Tageslimit überschritten oder ungültiger Betrag
return False
else:
self.Kontostand += betrag
self.UmsatzHeute += betrag
return True
def auszahlen(self, betrag):
if betrag < 0 or self.UmsatzHeute + betrag > self.MaxTagesumsatz:
# Tageslimit überschritten oder ungültiger Betrag
return False
else:
self.Kontostand -= betrag
self.UmsatzHeute += betrag
return True
def zeige(self):
print("Konto von {}".format(self.Inhaber))
print("Aktueller Kontostand: {:.2f} Euro".format(self.Kontostand))
print("(Heute schon {:.2f} von {} Euro umgesetzt)".format(
self.UmsatzHeute, self.MaxTagesumsatz))

An dieser Stelle haben wir unser Ziel erreicht, die Kontodaten und die dazugehörigen Verarbeitungsfunktionen zu einer Einheit zu verbinden.

Mithilfe der neuen Kontoklasse können wir die Geschäfte von Herrn Schmidt und Herrn Meier vom Beginn des Kapitels erneut durchspielen:

>>> k1 = Konto("Heinz Meier", 567123, 12350.0)
>>> k2 = Konto("Erwin Schmidt", 396754, 15000.0)
>>> k1.geldtransfer(k2, 160)
True
>>> k2.geldtransfer(k1, 1000)
True
>>> k2.geldtransfer(k1, 500)
False
>>> k2.einzahlen(500)
False
>>> k1.zeige()
Konto von Heinz Meier
Aktueller Kontostand: 13190.00 Euro
(Heute schon 1160.00 von 1500 Euro umgesetzt)
>>> k2.zeige()
Konto von Erwin Schmidt
Aktueller Kontostand: 14160.00 Euro
(Heute schon 1160.00 von 1500 Euro umgesetzt)

Im folgenden Abschnitt werden wir uns darüber Gedanken machen, wie wir unser Beispiel so strukturieren können, dass es sich leicht für neue Problemstellungen verallgemeinern lässt.

 


Ihre Meinung

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.

<< zurück
 Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Python 3 Python 3
Jetzt Buch bestellen

 Buchempfehlungen
Zum Rheinwerk-Shop: Einstieg in Python
Einstieg in Python


Zum Rheinwerk-Shop: Python. Der Grundkurs
Python. Der Grundkurs


Zum Rheinwerk-Shop: Algorithmen mit Python
Algorithmen mit Python


Zum Rheinwerk-Shop: Objektorientierte Programmierung
Objektorientierte Programmierung


Zum Rheinwerk-Shop: Raspberry Pi. Das umfassende Handbuch
Raspberry Pi. Das umfassende Handbuch


Zum Rheinwerk-Shop: Roboter-Autos mit dem Raspberry Pi
Roboter-Autos mit dem Raspberry Pi


Zum Rheinwerk-Shop: Neuronale Netze programmieren mit Python
Neuronale Netze programmieren mit Python


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo

 
 


Copyright © Rheinwerk Verlag GmbH 2020
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

 
[Rheinwerk Computing]

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern