Python dunder methods and operator overloading
__str__, __repr__, __len__, __eq__, __lt__, __add__, __getitem__, operator overloading, when to implement dunders
Dunder (Magic) Methods
Dunder methods (double underscore) let your class integrate with Python's built-in syntax and functions like print, len, +, and comparisons.
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Vector({self.x}, {self.y})"
def __str__(self):
return f"({self.x}, {self.y})"
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __eq__(self, other):
return self.x == other.x and self.y == other.y
def __len__(self):
return 2 # always 2 components
v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2) # (4, 6)
print(v1 == v2) # False
print(len(v1)) # 2
__repr__ vs __str__
__repr__ should return an unambiguous string that ideally lets you recreate the object. __str__ is the user-friendly display. If only __repr__ is defined, it is used as fallback for str() and print() as well. Always define at minimum __repr__ for any non-trivial class.
Dunder methods make your objects feel native to the language. When you implement __add__, your objects work with the + operator. When you implement __iter__ and __next__, they work in for loops. When you implement __contains__, the in operator works. This is called the data model and it is what gives Python its expressive, consistent feel. You do not need to implement every dunder — only those that make semantic sense for your type. An incomplete implementation is worse than none because it creates confusing partial support.
