16 Eigene Objekte definieren
Mit fertigen Objekten arbeiten ist eine tolle Sache. Eigene Objekte zu erstellen, ist die hohe Kunst. Aber auch um sinnvoll mit vorhandenen Objekten umgehen zu können, solltest du verstanden haben, wie Objekte aufgebaut sind und hergestellt werden.
Nun endlich wollen wir unseren Toaster doch einmal in seine Bestandteile zerlegen und sein Innenleben erforschen, denn zum einen sind Objekte viel besser zu verstehen und zu verwenden, wenn man weiß, wie sie in Python aufgebaut werden, zum anderen kommt man in späteren Programmprojekten nicht umhin, sich auch einmal eigene Objekte zu definieren oder zumindest umzuschreiben.
Nehmen wir jetzt also einmal an, es gibt unser Toaster-Objekt noch gar nicht. Wir haben nur eine Idee und wollen uns so ein Objekt erschaffen. Das heißt, wir müssen eine eigene Klassendefinition für einen Toaster erstellen.
Um eine neue Objektklasse zu erstellen, beginnen wir in Python immer mit dem Wörtchen
Um jetzt eine Objektklasse mit dem Namen »Toaster« zu definieren, lautet die erste Zeile ganz einfach:
class Toaster:
Danach folgt eingerückt alles, was zu dieser Klasse gehört. Das sind die Methoden und Funktionen des Objekts. Wenn du Eigenschaften des Toasters definieren willst (also Objektvariablen), geht das zum Beispiel einfach so:
class Toaster:
schaechte = 2
farbe = "grün"
anzahl_toasts = 0
toast_zeit = 10
Diese Eigenschaften kannst du jederzeit ändern, nachdem du ein Objekt der Klasse Toaster erzeugt hast.
Zum Beispiel so:
mein_toaster = Toaster()
mein_toaster.farbe = "rot"
mein_toaster.schaechte = 5
[ → ] Beachte die unterschiedlichen Schreibweisen für Klassennamen, Eigenschaftsnamen und Methodennamen (Groß- Kleinschreibung, camelCase und snake_case), wie im letzten Kapitel beschrieben.
Meistens werden die Startwerte eines Objekts aber bei seiner Erzeugung gesetzt. Und das geht am einfachsten mit der Startfunktion, der __init__-Methode.
Die Funktion »__init__«
Als Erstes wird in einer neu erstellten Objektklasse in der Regel die __init__-Funktion definiert. Das ist eine Funktion, die die meisten Objekte haben sollten – eine Spezialfunktion, die intern zum Objekt gehört. Gekennzeichnet werden interne Funktionen (die ein Programm auch nicht von außen aufrufen kann, sondern die automatisch starten) immer durch zwei Unterstriche vor und nach dem Schlüsselwort.
Wozu ist die »__init__«-Funktion gut?
init ist eine Abkürzung für initialization – also Initialisierung, Setzen der Grundeinstellungen für das Objekt. Die __init__-Funktion (die auch Konstruktor genannt wird) wird automatisch immer dann ausgeführt, sobald ein neues konkretes Objekt aus der Klasse erzeugt wird. Es ist quasi die Einrichtungsfunktion bei der Erstellung des Objekts.
Wenn ein Programm also ein Objekt mit mein_toaster = Toaster() erstellt, dann wird ein Objekt namens mein_toaster erzeugt – basierend auf der Klasse Toaster –, und sofort wird automatisch die __init__-Funktion von Toaster gestartet, damit das Objekt seine Grundeinstellungen erhält.
Die __init__-Funktion erhält als Parameter auch die Werte, die bei der Erstellung eines Objekts in Klammern übergeben werden. Sie kann diese dann benutzen, um damit die Objektvariablen zu setzen.
Konkret: Wenn ein neuer Toaster erstellt wird, soll er gleich die Werte für die Anzahl der Schächte und die Farbe mit erhalten, so wie wir es schon gemacht haben.
Das Objekt wird in Python etwa so erstellt:
mein_toaster = Toaster(2,"rot")
Die __init__-Funktion erhält diese beiden Werte und setzt sie entsprechend im Objekt.
def __init__(self,schaechte,farbe):
self.farbe = farbe
self.schaechte = schaechte
Weiterhin setzt die __init__-Funktion nun noch alle anderen Attribute (also die Objektvariablen), damit das Objekt grundlegende Eigenschaften hat, wenn es neu entsteht.
self.anzahl_toasts = 0
self.brot_zustand = 0
self.toast_zeit = 10
Was bedeutet dieses »self«?
self steht in der Klassendefinition immer für den Bezeichner des konkreten Objekts. self ist immer der erste Parameter, den eine Funktion in einem Objekt erhält. Dieser Parameter wird aber beim Aufrufen nicht in der Klammer mit übergeben, sondern er wird automatisch erzeugt und enthält immer das Objekt, das die Funktion aufruft.
Wenn ich also mein_toaster = Toaster(2,"rot") ausführe, dann wird ein Objekt namens mein_toaster erstellt. Für dieses Objekt mit dem Namen mein_toaster steht das self dann quasi als Platzhalter. Überall, wo self steht, kann man sich dann mein_toaster denken.
self.anzahl_toasts = 0 bedeutet für das Objekt namens mein_toaster also das gleiche wie mein_toaster.anzahl_toasts = 0
Es ist wichtig, dieses self zu verstehen, denn nur so kann man in einer Klassendefinition Funktionen schreiben, die etwas am Objekt selbst verändern. Die Objektdefinition (also die Klasse) weiß schließlich noch nicht, welches die Objekte sind, die man mit ihr anlegt, und soll für jedes Objekt gelten, das mit ihr erstellt wird. Daher steht überall dort, wo eigentlich der Objektbezeichner hingehört, ein self. Wenn dann ein Objekt erstellt wurde und für dieses Objekt Methoden aufgerufen werden, erhält jede Funktion immer als ersten Wert das Objekt selbst (self). Dieses wird nicht beim Aufruf übergeben, es kommt quasi beim Aufruf durch ein Objekt automatisch hinein und enthält das Objekt, das die Funktion aufruft. Auch eine Funktion ohne Parameter hat in der Definition immer genau einen Parameter – das self.
self könnte man also übersetzen mit »das Objekt selber«.
So sieht unsere Klassendefinition für den Toaster jetzt also aus:
class Toaster:
def __init__(self,schaechte,farbe):
self.schaechte = schaechte
self.farbe = farbe
self.anzahl_toasts = 0
self.brot_zustand = 0
self.toast_zeit = 10
Es wird eine Klasse definiert, die Toaster heißt. Beim Erstellen eines Objekts der Klasse »Toaster« werden die zwei Variablen schaechte und farbe mit übergeben – ein neues Objekt wird hier also immer mit diesen beiden Werten erstellt.
Beim Erstellen des Objekts wird die __init__-Funktion automatisch ausgeführt. Sie nimmt die zwei übergebenen Werte und schreibt sie in die beiden Objektvariablen schaechte und farbe. Außerdem definiert sie die weiteren Objektvariablen (Eigenschaften des Objekts) und gibt ihnen Anfangswerte. anzahl_toasts wird auf 0 gesetzt (klar, am Anfang ist der Toaster leer), brot_zustand wird auf 0 gesetzt (noch kein getoastetes Brot vorhanden), toast_zeit wird auf 10 gesetzt. Die Voreinstellung des Timers ist also 10 Sekunden.
Mit dieser Definition alleine kann man schon ein Objekt erstellen, das Eigenschaften hat.
Mit toasty = Toaster(4,"blau") könntest du ein Toaster-Objekt namens toasty anlegen, das 4 Schächte hat, das die Farbe Blau hat, das 0 Toasts drin hat und dessen Timer auf 10 Sekunden gestellt ist.
Du kannst dann auch schon alle Eigenschaften abfragen und ändern. toasty.toast_zeit = 20 würde den Timer auf 20 Sekunden setzen, mit f = toasty.farbe kannst du seine Farbe abfragen usw. …
Und es muss nicht bei einem bleiben – selbstverständlich kannst du jederzeit mehrere Toaster-Objekte mit verschiedenen Namen erstellen – so viele du möchtest, und jedes hat seine eigenen Eigenschaften und Zustände.
Zusammenfassung: Klassen
-
Um eine eigene Objektklasse zu erzeugen, schreibst du in Python eine Definition, die immer mit class Name: beginnt. Name steht dabei für den Namen, den deine Klasse haben soll, und beginnt mit einem Großbuchstaben.
-
Anschließend folgen eingerückt die Variablen (Eigenschaften), die das Objekt besitzen soll, sowie die Funktionen (Methoden), die das Objekt ausführen kann.
-
Variablen können einfach mit variablenname = wert innerhalb der Klassendefinition angegeben werden. Sie sind dann Objektvariablen, also Eigenschaften des Objekts, und können später mit objektname.eigenschaftsname verwendet werden.
-
Objektfunktionen (Methoden) werden in der Klassendefinition wie normale Funktionen mit def funktionsname (parameter) erzeugt, wobei der erste Parameter einer Funktion immer das self sein muss, danach können weitere Werte folgen, die der Funktion übergeben werden.
-
In Python gibt es bei Klassendefinitionen Spezialfunktionen wie die __init__-Funktion, die automatisch aufgerufen wird, wenn ein Objekt erzeugt wird, und die __str__-Funktion, die automatisch aufgerufen wird, wenn der Objektname als String verwendet werden soll.
-
Klassennamen werden immer mit großen Anfangsbuchstaben geschrieben. Alle anderen Variablen und Funktionen (Objektnamen, Eigenschaften, Methoden) werden wie alles andere auch in Python mit kleinen Anfangsbuchstaben begonnen, wobei ich für Methoden in TigerJython die Schreibweise camelCase empfehle.
Zusammenfassung: Objektprogrammierung
-
Objekte sind unter einem bestimmten Namen zusammengefasste Bündel von Variablen (Eigenschaften) und Funktionen (Methoden).
-
Ein Python-Objekt kann wie Objekte in der Wirklichkeit Eigenschaften und Fähigkeiten haben.
-
Die Beschreibung eines Objekts ist die Klasse des Objekts. Sie wird in der Klassendefinition genau festgelegt. Die Klassendefinition enthält alle Variablen und Funktionen, die dem Objekt zur Verfügung stehen.
-
Die Klasse ist aber nicht das Objekt, so wie das Rezept nicht der Kuchen ist. Aus einer Klasse kann jederzeit ein Objekt erstellt werden (oder mehrere), das dann alle in der Klasse definierten Fähigkeiten hat.
-
Gut programmierte Objekte sind wie eigenständige Elemente eines Programms, denen man Eigenschaften zuweisen und Befehle geben kann, die sie selbstständig ausführen.
-
Objektklassen können entweder von Grund auf neu programmiert werden, oder sie basieren auf einer schon vorhandenen Klasse und erweitern oder verändern diese (Vererbung von Klassen).
-
Für Python gibt es unzählige vordefinierte Objekte, die du einfach importieren und benutzen kannst. Du musst dazu nur wissen, wie die Eigenschaften und Methoden des Objekts heißen, wie sie angesprochen werden und was sie bewirken. Das Arbeiten mit vordefinierten Objekten bietet sehr umfangreiche Möglichkeiten beim Programmieren, die vergleichsweise wenig Aufwand bedeuten.