Magische methoden (of dunder-methoden – van double underscore) zijn speciale methoden waarvan de naam begint en eindigt met twee onderstrepingen, bijvoorbeeld __init__, __str__, __add__. Ze stellen je in staat om instanties van eigen klassen in de syntaxis en het gedrag van Python in te voegen: de reactie op wiskundige operaties, vergelijkingen, omzetting naar strings, werken met collectieve protocollen, enzovoort.
Voorbeeld:
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) # Roep v1.__add__(v2) aan, retourneert Vector(4, 6)
Als je
__eq__niet implementeert in je eigen klasse, hoe worden de instanties dan vergeleken met de operator==?
Antwoord: Standaard vergelijkt de operator == objecten op identiteit (adres in geheugen, vergelijkbaar met de operator is), tenzij je de magische methode __eq__ hebt overschreven.
class A: pass print(A() == A()) # False, hoewel de objecten "gelijk lijken"
Verhaal
In een project waar het nodig was om de structuren van een graaf te vergelijken, werd de methode __eq__ niet geïmplementeerd. Hierdoor kreeg je bij het controleren "is de knoop al toegevoegd" een onjuist resultaat, omdat de operator == de objecten vergeleek op id, en niet op de inhoud.
Verhaal
Bij het schrijven van een REST API werden objecten in een string voor de log geserialiseerd via str(obj), maar we vergaten __str__ te definiëren. Als gevolg hiervan werd er een onleesbare tekst <MyObj object at 0x...> weergegeven, wat de probleemdiagnose bemoeilijkte.
Verhaal
In een bibliotheek voor wiskundige berekeningen werd alleen __add__ geïmplementeerd, maar werd __iadd__ voor de operator += vergeten. Dit resulteerde erin dat de expressie v += w niet werkte zoals verwacht (er werd een nieuw object aangemaakt, het oude werd niet bijgewerkt), wat leidde tot geheugenlekken in complexe berekeningen.