Python Magic Methods
In this page:
What are Magic Methods?
Magic methods (also called dunder methods, for their double underscores like __init__) are special hooks Python calls automatically for built-in operations -- defining __init__ lets you customize object construction, while other dunders let you customize printing, comparison, arithmetic, and more.
Example: What are Magic Methods?
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
p = Point(1, 2)
print(p.x, p.y)
Operator Overloading
Defining __add__(self, other) on a class lets the + operator work on your own objects -- write two Vector objects and v1 + v2 calls v1.__add__(v2) behind the scenes, letting you return a new Vector with summed components instead of Python raising a TypeError.
Example: Operator Overloading
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)
v = Vector(1, 2) + Vector(3, 4)
print(v.x, v.y)
Comparison Magic Methods
Overloading __eq__ lets you define what '==' means for your class (like comparing two Point objects by their x/y coordinates rather than by identity), and __lt__ defines '<' so that built-ins like sorted() and min() know how to order your objects.
Example: Comparison Magic Methods
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __eq__(self, other):
return self.x == other.x and self.y == other.y
print(Point(1, 2) == Point(1, 2))
Length and Container Methods
Defining __len__ makes len(my_object) work on your custom class, and __getitem__ lets it support square-bracket indexing (my_object[0]) -- together these two are often enough to make a custom class usable anywhere a list or dict would be expected.
Example: Length and Container Methods
class Basket:
def __init__(self, items):
self.items = items
def __len__(self):
return len(self.items)
def __getitem__(self, index):
return self.items[index]
b = Basket(["apple", "banana"])
print(len(b), b[0])
Making Objects Callable
Implementing __call__ lets you invoke an instance directly like a function -- my_object() -- which is useful for objects that wrap some configurable behavior, such as a class that remembers settings and then runs a computation when called.
Example: Making Objects Callable
class Multiplier:
def __init__(self, factor):
self.factor = factor
def __call__(self, x):
return x * self.factor
times3 = Multiplier(3)
print(times3(10))
Chapter Quiz — Complete all 11 topics to unlock
0/11 topics done
Complete these topics first: