Methoden mit doppelten Unterstrichen wie __init__ heißen Dunder-Methoden (double underscore) oder magische Methoden. Python ruft sie automatisch auf, wenn du Operatoren und eingebaute Funktionen auf deine Objekte anwendest. So verhalten sich eigene Klassen wie eingebaute Typen.
Überblick
| Methode | Wird aufgerufen bei |
|---|---|
__init__ | Klasse(...) |
__str__, __repr__ | str(x), print(x), repr(x) |
__len__ | len(x) |
__getitem__ | x[i] |
__contains__ | a in x |
__iter__, __next__ | for a in x |
__add__, __sub__, __mul__ | x + y, x - y, x * y |
__eq__, __lt__ | x == y, x < y |
__bool__ | if x: |
__call__ | x(...) |
__enter__, __exit__ | with x: |
Rechnen mit eigenen Objekten
class Vektor:
def __init__(self, x, y):
self.x, self.y = x, y
def __add__(self, o):
return Vektor(self.x + o.x, self.y + o.y)
def __mul__(self, k):
return Vektor(self.x * k, self.y * k)
def __eq__(self, o):
return (self.x, self.y) == (o.x, o.y)
def __repr__(self):
return f"Vektor({self.x}, {self.y})"
a, b = Vektor(1, 2), Vektor(3, 4)
print(a + b)
print(a * 3)
print(a + b == Vektor(4, 6))Vektor(4, 6) Vektor(3, 6) True
Sich wie eine Sammlung verhalten
class Regal:
def __init__(self, *buecher):
self.buecher = list(buecher)
def __len__(self):
return len(self.buecher)
def __getitem__(self, i):
return self.buecher[i]
def __contains__(self, titel):
return titel in self.buecher
r = Regal("Faust", "Momo", "Ronja")
print(len(r), r[1], "Momo" in r)
for buch in r: # funktioniert dank __getitem__
print("-", buch)3 Momo True - Faust - Momo - Ronja
Vergleichen und Sortieren
Mit __lt__ lassen sich Objekte sortieren. Der Dekorator functools.total_ordering ergänzt die restlichen Vergleiche:
from functools import total_ordering
@total_ordering
class Version:
def __init__(self, text):
self.teile = tuple(int(t) for t in text.split("."))
def __eq__(self, o):
return self.teile == o.teile
def __lt__(self, o):
return self.teile < o.teile
def __repr__(self):
return "v" + ".".join(map(str, self.teile))
liste = [Version("1.10.0"), Version("1.2.5"), Version("1.2.10")]
print(sorted(liste))
print(max(liste), Version("2.0") >= Version("1.9"))[v1.2.5, v1.2.10, v1.10.0] v1.10.0 True
Aufrufbare Objekte
class Verdoppler:
def __init__(self, faktor=2):
self.faktor = faktor
def __call__(self, x):
return x * self.faktor
dopple = Verdoppler()
print(dopple(21))
print(list(map(Verdoppler(10), [1, 2, 3])))42 [10, 20, 30]
Kontext-Manager
Mit __enter__ und __exit__ kannst du eigene with-Blöcke bauen, genau wie bei Dateien:
class Abschnitt:
def __init__(self, name):
self.name = name
def __enter__(self):
print(f"--- {self.name} beginnt")
return self
def __exit__(self, typ, wert, spur):
print(f"--- {self.name} endet")
return False # Fehler nicht verschlucken
with Abschnitt("Test"):
print("mittendrin")--- Test beginnt mittendrin --- Test endet
Merke
- Dunder-Methoden werden von Python automatisch aufgerufen
__add__,__eq__,__lt__& Co. überladen Operatoren__len__,__getitem__,__contains__machen Objekte zu Sammlungen__call__macht Objekte aufrufbar__enter__/__exit__bauen eigenewith-Blöcke@total_orderingspart Vergleichsmethoden
Aufgabe
Baue eine Klasse Geld mit Betrag und Währung, die sich addieren und vergleichen lässt und schön ausgibt (zum Beispiel 12.50 EUR).