Introduction
Methods with double underscores on both sides, such as __init__, are special methods. Python calls them for you when you use built-in operations: print, +, ==, len() and more.
A class of your own can feel as natural as a number or a list. Special methods are the hooks that let your objects work with print, +, == and len, so code that uses them reads like ordinary Python.
How it works
Printing an object
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f"({self.x}, {self.y})"
p = Point(3, 4)
print(p)Without __str__, print(p) would show something like <Point object at 0x...>. With it, Python calls p.__str__() to get the text. Step through print(p) and watch the __str__ frame appear on the call stack.
len()
class Playlist:
def __init__(self, songs):
self.songs = songs
def __len__(self):
return len(self.songs)
mix = Playlist(["a", "b", "c"])
print(len(mix))len(mix) calls mix.__len__(). Implementing the special methods that fit your class makes it feel like a built-in type.
| You write | Python calls |
|---|---|
print(x), str(x) | x.__str__() |
x + y | x.__add__(y) |
x == y | x.__eq__(y) |
len(x) | x.__len__() |
Syntax
class Money:
def __init__(self, taka):
self.taka = taka
def __str__(self):
return f"{self.taka} taka"
def __add__(self, other):
return Money(self.taka + other.taka)
Example
class Money:
def __init__(self, taka):
self.taka = taka
def __add__(self, other):
return Money(self.taka + other.taka)
def __eq__(self, other):
return self.taka == other.taka
def __str__(self):
return f"{self.taka} taka"
total = Money(150) + Money(250)
print(total)
print(total == Money(400))a + bcallsa.__add__(b), which here returns a new Money object.a == bcallsa.__eq__(b). Without it,==only checks whether both names point to the same object.
The objects panel shows the temporary Money objects being created and the result being kept in total.
Line by line
Money(150) + Money(250)makes two objects and then calls__add__.__add__returns a newMoneyholding 400, and it is stored intotal.print(total)calls__str__, which gives400 taka.total == Money(400)calls__eq__, which compares the amounts.
Expected result
400 taka
True
In the real world
Python's own datetime objects support subtraction this way, and the Fraction and Decimal types behave just like numbers. Scientific libraries use special methods so that matrix code looks like the maths it represents.
Common mistakes
- Returning something other than text from
__str__, which raises aTypeError. - Changing
selfinside__add__instead of returning a new object:a + bshould not changea. - Calling special methods directly (
p.__str__()) in normal code; usestr(p)and let Python call them.
Best practices
- Add
__str__to almost every class you write. - Only overload an operator when its meaning is obvious.
- Keep
__add__free of side effects.
Summary
Special methods connect a class to Python's built-in operations. __str__ gives the printed form, __add__ and __eq__ give + and == their meaning, and __len__ supports len.
Practice
Give the Point class an __add__ that adds coordinates and an __eq__ that compares them, then check that Point(1, 2) + Point(3, 4) == Point(4, 6).
Quick check
Key takeaways
- print calls __str__ and == calls __eq__.
- __add__ should return a new object.
- Let Python call special methods, rather than calling them yourself.
Practice problems for this lesson
My notes
Write down what you want to remember from this lesson. Notes are saved on this device as you type, and appear on your dashboard.