Python: Was ist der Unterschied zwischen __str__ und __repr__?
Beide machen aus einem Objekt einen String. __str__ ist für Menschen,
__repr__ ist für dich, wenn etwas schiefgegangen ist — und wenn du nur eine
von beiden definierst, dann __repr__.
Der Unterschied bei eingebauten Typen
str : a string repr : 'a string'
str : 3.0 repr : 3.0
str : 2026-08-29 repr : datetime.date(2026, 8, 29)
str : 0.1 repr : Decimal('0.1')
str : None repr : None
Die Zeile mit dem Datum zeigt die Absicht. str liefert dir etwas für eine
Seite, repr liefert dir etwas, das genau sagt was das Objekt ist — samt Typ.
Die Zeile mit dem String ist die, der man täglich begegnet: repr behält die
Anführungszeichen, du kannst also 1 von "1" unterscheiden.
Wo du welche bekommst
print(s) : line
break
print([s]) : ['line\nbreak']
print() verwendet str. Ein Container verwendet repr für seine
Elemente — immer, auch wenn du den Container ausgibst. Deshalb sieht eine Liste
deiner Objekte anders aus, als eines davon auszugeben.
Der interaktive Interpreter gibt repr aus. Deshalb zeigt ein Wert an der
Eingabeaufforderung Anführungszeichen und print() nicht.
In einem f-String wählst du selbst: !s für str, !r für repr.
Definiere zuerst repr
Das ist die praktische Regel, und sie folgt aus einem Rückfallweg:
class NurRepr:
def __repr__(self): return "NurRepr(x=1)"
str(o) : OnlyRepr(x=1)
repr(o) : OnlyRepr(x=1)
str() fällt auf __repr__ zurück, wenn es kein __str__ gibt. Nur
__repr__ zu definieren liefert dir also überall eine brauchbare Ausgabe.
Umgekehrt gilt das nicht:
with only __str__, repr(p) : <__main__.OnlyStr object at 0x...
[p] in a list : [<__main__.OnlyStr object at 0x7ede07e3738...
Definierst du nur __str__, sind deine Objekte in einer Liste, einem
Dictionary, einem Debugger oder einer protokollierten Datenstruktur unlesbar —
also genau dann, wenn du sie lesen musst.
Beide, wenn sie sich unterscheiden
class Geldbetrag:
def __init__(self, c): self.cent = c
def __repr__(self): return f"Geldbetrag(cent={self.cent})"
def __str__(self): return f"{self.cent / 100:.2f} EUR"
print(m) : 4.99 EUR
repr(m) : Money(cents=499)
[m] : [Money(cents=499)]
Der Benutzer sieht 4.99 EUR. Du siehst Money(cents=499), und das sagt dir,
dass es Cent sind und keine Euro — genau die Unterscheidung, die man um drei
Uhr morgens gerne hätte.
Die Regel für repr
Die Dokumentation verlangt etwas Eindeutiges, und idealerweise etwas, das man wieder einfügen könnte:
repr(a date) : datetime.date(2026, 8, 29)
eval works? : True
str(a date) : 2026-08-29 <- not valid Python
eval(repr(x)) == x ist ein Ziel und keine Pflicht — viele Objekte schaffen
das nicht. Wenn es nicht geht, sind spitze Klammern die Konvention, um “das ist
eine Beschreibung und kein Ausdruck” zu signalisieren:
def __repr__(self):
return f"<Verbindung zu {self.host}, {'offen' if self.offen else 'geschlossen'}>"
Der Fall mit den Fließkommazahlen
str : 0.30000000000000004
repr : 0.30000000000000004
float(repr(f)) == f : True
Seit Python 3.1 stimmen die beiden bei Fließkommazahlen überein, und beide
liefern den kürzesten String, der exakt zurückkonvertiert. Davor rundete
str() auf 12 signifikante Stellen und repr() gab 17 aus — daher stammt der
alte Rat, die beiden würden sich unterscheiden. Er ist überholt.
Protokolliere repr, nicht str
str(exc) : division by zero
repr(exc) : ZeroDivisionError('division by zero')
str() einer Exception liefert die Nachricht und sonst nichts. repr()
liefert die Nachricht und den Typ. In einer Logdatei ist “division by zero”
ohne den Klassennamen deutlich weniger wert, und der Unterschied kostet nichts.
Dieselbe Überlegung gilt für logging: %r statt %s für alles, was du
später einmal identifizieren musst.
Ein Hinweis zu dataclasses
@dataclass erzeugt dir
ein __repr__, und zwar genau in der oben beschriebenen Form. Für einen
einfachen Datencontainer bekommst du das also geschenkt und solltest keines von
Hand schreiben. Ein __str__ wird nicht erzeugt, und das ist die richtige
Voreinstellung — die meisten Objekte brauchen keines.
Hinweis zu Netcup (Werbung)
Der deutsche Hoster Netcup bietet unter anderem günstige und zugleich leistungsstarke Webhosting Pakete, KVM-basierte Root Server und dezidierte Server an. Mit unseren Gutscheincodes kannst du noch mehr Geld sparen (6€ bei deiner ersten Bestellung, 30% Rabatt auf alle KVM-basierten Root Server, ...).