Magic methods (or dunder methods – from double underscore) are special methods whose names begin and end with double underscores, for example, __init__, __str__, __add__. They allow you to integrate instances of your own classes into the syntax and behavior of Python: define reactions to arithmetic operations, comparisons, string conversions, work with collection protocols, etc.
Example:
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) # Calls v1.__add__(v2), returns Vector(4, 6)
If you do not implement
__eq__in your own class, how will its instances be compared using the==operator?
Answer: By default, the == operator compares objects by identity (memory address, similar to the is operator) unless the magic method __eq__ is overridden.
class A: pass print(A() == A()) # False, even though the objects "seem identical"
Story
In a project where it was necessary to compare graph structures, the __eq__ method was not implemented. As a result, when checking "is the node already added," an incorrect result was obtained because the == operator compared objects by id, not by content.
Story
When writing a REST API, an object was serialized into a string for logging via str(obj), but the __str__ was not defined. As a result, an unreadable text <MyObj object at 0x...> was output, which complicated the diagnosis of issues.
Story
In a library for mathematical computations, only __add__ was implemented, but __iadd__ for the += operator was forgotten. Consequently, the expression v += w did not work as expected (a new object was created, the old one was not updated), leading to memory leaks in complex computations.