Konstruktoren und self
Kurz gesagt: Der Konstruktor in Python ist die Methode __init__, die beim Erzeugen des Objekts läuft und seine Attribute über self füllt.
Problem
Kaffee für 0 €
Du erzeugst ein Produkt, genau wie in der letzten Lektion, und füllst die Felder Zeile für Zeile. Eine Zeile hast du vergessen:
coffee = Product()coffee.name = "Kaffee"coffee.quantity = 2print(f"{coffee.name}: {coffee.price * coffee.quantity} €")Kaffee: 0.0 €Der Kaffee kostet 0 €. Python beschwert sich nicht: Der Preis hat einen Wert, 0.0 aus __init__. Je mehr Felder eine Klasse hat, desto leichter vergisst du eines. Und ein Produkt ohne Preis sollte es gar nicht geben können.
Die Idee
Konstruktor: ohne diese Daten kein Objekt
Eine Klasse kann sagen, was sie braucht, bevor du ein Objekt aus ihr erzeugen kannst. Dafür gibt es den Konstruktor: eine besondere Methode, die bei Product(...) läuft. In Python ist das __init__, das du schon kennst, nur dass es jetzt Parameter nimmt.
class Product: def __init__(self, name, price, quantity): self.name = name self.price = price self.quantity = quantity
coffee = Product("Kaffee", 7.50, 2)print(f"{coffee.name}: {coffee.price * coffee.quantity} €")Kaffee: 15.0 €- Der Konstruktor heißt
__init__(zwei Unterstriche davor und zwei danach), in jeder Klasse. - Sein erster Parameter ist
self: das Objekt, das gerade entsteht. Python übergibt es für dich. - Die anderen Parameter sind die Daten, ohne die ein Produkt nicht auskommt. Du übergibst sie in den Klammern:
Product("Kaffee", 7.50, 2). - Er gibt nichts zurück.
Product(...)gibt das neue Objekt zurück.
Jetzt kannst du den Preis nicht mehr vergessen. Wenn du zwei Argumente statt drei übergibst, hält das Programm genau in dieser Zeile an:
coffee = Product("Kaffee", 7.50)TypeError: Product.__init__() missing 1 required positional argument: 'quantity'class Product: def __init__(self, name, price, quantity): self.name = name self.price = price self.quantity = quantity
coffee = Product("Kaffee", 7.50, 2)print(f"{coffee.name}: {coffee.price * coffee.quantity} €")Schritt für Schritt, in Worten
- Product(...) erzeugt ein neues Objekt. Es hat noch keine Felder: __init__ legt sie an.
- __init__ läuft. self ist das neue Objekt, und die Argumente gehen in die Parameter.
- self.name = name: vom Parameter in ein neues Feld dieses Objekts.
- Dasselbe für Preis und Stückzahl.
- __init__ ist fertig, und die Parameter verschwinden. coffee bekommt einen Pfeil auf das fertige Objekt.
- Das Objekt kommt schon gefüllt aus Product(...), deshalb ist der Preis nicht 0.
Die Idee
self: das Feld dieses Objekts
In __init__ gibt es zwei Dinge namens name: den Parameter und das Feld. name ist der Parameter. Das Feld ist self.name.
class Product: def __init__(self, name, price, quantity): self.name = name self.price = price self.quantity = quantityself ist das Objekt, das gerade entsteht. self.name = name bedeutet „speichere den Parameter name im Feld name dieses Objekts“.
In Python ist self. Pflicht. Ohne es ist name = name nur eine Variable in __init__, und sie verschwindet, sobald __init__ endet. Der Name self ist eine Abmachung, kein Schlüsselwort, aber alle schreiben ihn so.
Probier es aus
Finde den Fehler
AttributeError: 'Product' object has no attribute 'name' ab. In welcher Zeile ist der Fehler?Wähle die Zeile mit dem Fehler.
name = name speichert den Parameter in sich selbst. Das Feld name wird nie angelegt, also gibt es tea.name nicht. Du brauchst self.name = name. Der Fehler zeigt sich erst in der Zeile, die den Namen liest, weit weg von der eigentlichen Ursache.
Die Idee
Und Product() aus der letzten Lektion?
In der letzten Lektion hatte __init__ außer self keine Parameter, deshalb hat Product() funktioniert. Jetzt braucht __init__ drei Argumente, und ohne sie hält das Programm an:
empty = Product()TypeError: Product.__init__() missing 3 required positional arguments: 'name', 'price', and 'quantity'Genau darum geht es: Ein Produkt ohne Name und Preis lässt sich nicht mehr erzeugen.
Genauer, für Neugierige
Wenn eine Klasse gar kein __init__ hat, funktioniert Product() trotzdem: Python erzeugt ein Objekt ganz ohne Felder. Deshalb werden Felder in Python immer in __init__ angelegt.
Die Idee
Eine Standard-Stückzahl
Die meisten Produkte im Warenkorb kommen einzeln. Jedes Mal 1 zu tippen wird lästig.
In Python hat eine Klasse ein __init__. Statt eines zweiten Konstruktors bekommt der Parameter einen Standardwert: Wenn du keine Stückzahl übergibst, ist sie 1.
class Product: def __init__(self, name, price, quantity=1): self.name = name self.price = price self.quantity = quantityquantity=1 (ohne Leerzeichen um =) bedeutet „wenn keine Stückzahl übergeben wird, nimm 1“. Parameter mit Standardwert stehen am Ende. Wenn du nach quantity=1 einen Parameter ohne Standardwert schreibst, führt Python die Datei nicht aus:
SyntaxError: parameter without a default follows parameter with a defaultGenauer, für Neugierige
Ein zweites __init__ in der Klasse ergibt keinen zweiten Konstruktor. Es ersetzt einfach das erste, ohne Warnung, und Product("Brot", 1.20) bricht ab mit:
TypeError: Product.__init__() missing 1 required positional argument: 'quantity'Deshalb hat Python nur einen Konstruktor. Der Vorteil: Wenn du morgen eine Prüfung des Preises hinzufügst, steht sie an einer Stelle.
Probier es aus
Welcher Konstruktor?
Was gibt das Programm aus?
class Product: def __init__(self, name, price, quantity=1): self.name = name self.price = price self.quantity = quantity
bread = Product("Brot", 1.20)milk = Product("Milch", 2.10, 3)print(bread.quantity, milk.quantity)Product("Brot", 1.20) hat keine Stückzahl, also nimmt quantity den Standardwert 1. Für die Milch wird die Stückzahl übergeben: 3.Probier es aus
Wie heißt der Konstruktor?
Was steht in der Lücke?
class Book:
def (self, title, author):
self.title = title
self.author = author__init__: So heißt der Konstruktor in jeder Klasse, mit zwei Unterstrichen auf jeder Seite.Übung
Objekte, die vollständig entstehen
Löse die Aufgaben in deinem Editor. Jede Klasse bekommt einen Konstruktor mit Parametern für alle ihre Felder.
1. Person. Eine Klasse Person mit Name und Alter. Erzeuge zwei Personen und gib ihre Daten aus.
Maria, 34 JahrePeter, 19 Jahre2. Tier. Eine Klasse Animal mit Art und Alter. Erzeuge eine 3 Jahre alte Katze und einen 7 Jahre alten Hund.
Art: Katze, Alter: 3Art: Hund, Alter: 73. Tanzschritt. Eine Klasse DanceMove mit Name und Dauer in Sekunden. In der Lektion „Instanzmethoden“ lernt der Schritt, sich selbst „auszuführen“.
moonwalk: 5 Sek.Weitere Aufgaben
- Ein Buch mit Konstruktor. Schreib
Bookaus der letzten Lektion mit einem Konstruktor__init__(self, title, author)neu. Wie viele Zeilen sparst du in dem Code unter der Klasse? -
Ein Produkt mit Standard-Stückzahl.
Productmitquantity=1, wie in der Lektion. Leg eine Liste[Product("Brot", 1.20, 2), Product("Kaffee", 7.50)]an und gib von jedem Name und Stückzahl aus: „Brot x2“, „Kaffee x1“. - Buchung. Eine Klasse
Bookingmit dem Namen des Gastes, der Anzahl der Nächte und dem Preis pro Nacht. Gib aus, was der Aufenthalt kostet: Für 3 Nächte zu 85 € sind das 255 €.
Test
Teste dich
Verwandte Lektionen
Abschnitt „Verwandte Lektionen“- Baut auf: Listen · Funktionen · Parameter und return · Klassen und Objekte
- Geht weiter in: Instanzmethoden · Kapselung · Was alle Objekte teilen: Klassenattribute · Vererbung
- Aufgaben zum Thema: Klassen und Objekte