Metody magiczne (lub metody dunder – od podwójnego podkreślenia) to specjalne metody, których nazwy zaczynają się i kończą dwoma podkreśleniami, na przykład __init__, __str__, __add__. Umożliwiają one wbudowanie instancji własnych klas w składnię i zachowanie Pythona: określanie reakcji na operacje arytmetyczne, porównania, konwersję na ciągi znaków, pracę z protokołami kolekcji itp.
Przykład:
class Vector: def __init__(self, x, y): self.x = x self.y = y def __add__(self, other): return Vector(self.x + other.x, self.y + other.y) def __str__(self): return f"Vector({self.x}, {self.y})" v1 = Vector(1, 2) v2 = Vector(3, 4) print(v1 + v2) # Wywoła v1.__add__(v2), zwróci Vector(4, 6)
Jeśli nie zaimplementuje się
__eq__w swojej klasie, jak będą porównywane jej instancje za pomocą operatora==?
Odpowiedź: Domyślnie operator == porównuje obiekty według tożsamości (adresu w pamięci, podobnie jak operator is), jeśli nie nadpisano metody magicznej __eq__.
class A: pass print(A() == A()) # False, chociaż obiekty "wydają się identyczne"
Historia
W projekcie, w którym trzeba było porównywać struktury grafu, nie zaimplementowano metody __eq__. W wyniku tego sprawdzanie "czy węzeł już został dodany" dawało niepoprawny wynik, ponieważ operator == porównywał obiekty według id, a nie według zawartości.
Historia
Podczas pisania REST API zserializowano obiekt do ciągu znaków w logach przez str(obj), ale zapomniano zdefiniować __str__. W rezultacie wyświetlano nieczytelny tekst <MyObj object at 0x...>, co utrudniało diagnostykę problemów.
Historia
W bibliotece do obliczeń matematycznych zaimplementowano tylko __add__, ale zapomniano o __iadd__ dla operatora +=. W rezultacie wyrażenie v += w działało nie zgodnie z oczekiwaniami (tworzony był nowy obiekt, nie aktualizowano starego), co prowadziło do wycieków pamięci w złożonych obliczeniach.