Abschnitt 14 · Lektion 3
Schöne Ausgabe
Du willst ein Objekt einfach mal ausgeben. Ein Konto, einen Artikel oder eine Buchung, zum Nachsehen oder mitten in einem Satz. Bisher steht dann etwas da, mit dem niemand etwas anfangen kann.
Was print von einem Objekt weiß
class Artikel:
def __init__(self, name, preis, bestand):
self.name = name
self.preis = preis
self.bestand = bestand
brot = Artikel("Brot", 2.49, 12)
print(brot)
print(f"Heute im Angebot: {brot}") <__main__.Artikel object at 0x7f…> meint ein Objekt der Klasse Artikel aus der gestarteten
Datei, das an dieser Stelle im Speicher liegt. Die Zahl dahinter ist eine Speicheradresse. Sie ist
bei jedem Lauf eine andere.
Python weiß schlicht nicht, was an einem Artikel wichtig ist. Der Name? Der Preis? Alles? Das muss in der Klasse stehen.
Text für Menschen
class Artikel:
def __init__(self, name, preis, bestand):
self.name = name
self.preis = preis
self.bestand = bestand
def __str__(self):
return f"{self.name} für {self.preis:.2f} Euro"
brot = Artikel("Brot", 2.49, 12)
milch = Artikel("Milch", 1.19, 30)
print(brot)
print(f"Heute im Angebot: {milch}")
print([brot, milch]) Dafür gibt es __str__, eine Methode mit festem Namen. Sie gibt den Text zurück, der für das Objekt
stehen soll. Aufgerufen wird sie von Python selbst, sobald das Objekt als Text gebraucht wird. Bei
print(brot) steht deshalb Brot für 2.49 Euro da, im f-String genauso, und str(brot) gibt
denselben Text zurück.
Methoden mit zwei Unterstrichen auf jeder Seite ruft man fast nie selbst auf. Das macht Python, wenn
es so weit ist. __init__ war die erste davon.
Nur die letzte Zeile sieht aus wie vorher. In der Liste steht wieder zweimal die Speicheradresse,
weil eine Liste ihre Einträge nicht für Menschen zeigt, sondern so, dass man sie auseinanderhalten
kann. Bei Text war das schon immer so. print("Brot") schreibt Brot, print(["Brot"]) dagegen
['Brot'], mit Anführungszeichen, damit man sieht, dass es Text ist.
Text für Entwickler
class Artikel:
def __init__(self, name, preis, bestand):
self.name = name
self.preis = preis
self.bestand = bestand
def __str__(self):
return f"{self.name} für {self.preis:.2f} Euro"
def __repr__(self):
return f"Artikel({repr(self.name)}, {self.preis}, {self.bestand})"
regal = [Artikel("Brot", 2.49, 12), Artikel("Milch", 1.19, 30)]
print(regal)
print(regal[0])
print(repr(regal[0])) Diese zweite Darstellung kommt aus __repr__. Sie ist für alle gedacht, die nachsehen wollen, was
in einem Objekt steckt. Am besten sieht sie aus wie der Aufruf, mit dem man das Objekt anlegt, also
Artikel('Brot', 2.49, 12). repr(self.name) setzt den Namen dabei in Anführungszeichen, so wie
Python Text in einer Liste zeigt.
Jetzt steht die Liste lesbar da. print(regal[0]) nimmt weiterhin __str__, und repr() fragt
ausdrücklich nach __repr__.
Auch im Reiter Debug steht jetzt, was __repr__ liefert. Statt der Adresse siehst du dort
regal = [Artikel('Brot', 2.49, 12), Artikel('Milch', 1.19, 30)]. Nur in __init__ steht self
als <Artikel instance at 0x…> da. __repr__ fragt nach Name, Preis und Bestand, und die bekommt
das Objekt dort erst nach und nach.
Die Prüfdateien dieses Kurses nehmen übrigens auch repr(), wenn pruefe() Argumente und
Ergebnisse hinschreibt. Und gibt es nur __repr__ und kein __str__, nimmt print ebenfalls
__repr__. Andersherum gilt das nicht.
print statt return
class Artikel:
def __init__(self, name, preis, bestand):
self.name = name
self.preis = preis
self.bestand = bestand
def __str__(self):
print(f"{self.name} für {self.preis:.2f} Euro")
brot = Artikel("Brot", 2.49, 12)
print(brot) Hier gibt __str__ den Text aus, statt ihn zurückzugeben. Er steht sogar da, denn das print in
der Methode läuft ja. Das äußere print bekommt danach aber None statt Text, und Python bricht
ab: TypeError: __str__ returned non-string (type NoneType).
Gemeint ist, dass __str__ Text zurückgeben muss und hier nichts kam. Es ist derselbe Unterschied
zwischen ausgeben und zurückgeben wie bei jeder Funktion. Nur fällt er hier Python selbst auf.
Was die Aufgabe will
Das Konto mit seinen zwei Methoden bekommt beide Darstellungen. Die für Menschen zeigt den Inhaber
und den Stand als deutschen Betrag, mit euro() aus Lektion 8.2. Die für Entwickler sieht so aus,
wie man das Konto anlegt.
Zum Mitnehmen
__str__ legt fest, was print und ein f-String von einem Objekt zeigen, also die Fassung für Menschen. __repr__ ist für Entwickler und erscheint in Listen, im Reiter Debug und bei repr(), am besten in der Form, in der man das Objekt anlegt. Beide geben ihren Text mit return zurück, und ein print an dieser Stelle führt zu einem TypeError.
Jetzt du
Basis Konto, kostenlosZu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.
Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.
In diesem Kurs läuft dein Code auf einem Server. Dafür hat das Basis Konto 1 Stunde im Monat, mehr Zeit gibt es mit dem Premium Konto.
Was in dieser Lektion steckt
-
Artikel mit 4 Beispielen zum Ausprobieren
Steht hier, ohne Konto lesbar.
-
Aufgabe, dein Code läuft auf einem Server
Öffnet sich mit dem Basis Konto.