Skip to content
FollowtheDamnCode

Dunder Methods

Making objects print, add, and compare.

5 minute read

Big idea

Dunder methods — short for "double underscore", like __str__ and __add__ — let your objects work with Python's built-in syntax: print(obj), a + b, a == b, len(obj).

str and repr

By default, printing an object isn't helpful:

print(Point(3, 4))   # <__main__.Point object at 0x104f2b7d0>

Define __str__ to choose what print and str() show, and __repr__ for the developer view (what the shell and lists show):

A printable point
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        return f"({self.x}, {self.y})"

    def __repr__(self):
        return f"Point({self.x}, {self.y})"

p = Point(3, 4)
print(p)
print([p, Point(0, 0)])
output
(3, 4)
[Point(3, 4), Point(0, 0)]

Run and edit it in the app.

Operators

Python turns a + b into a.__add__(b), and a == b into a.__eq__(b). Define them, and your objects work with the operators:

Predict: adding and comparing vectors
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 __eq__(self, other):
        return self.x == other.x and self.y == other.y

    def __str__(self):
        return f"<{self.x}, {self.y}>"

a = Vector(1, 2)
b = Vector(3, 4)
print(a + b)
print(a + b == Vector(4, 6))
print(a == b)
What does it print? Show the answer
<4, 6>
True
False

Run and edit it in the app.

__add__ returns a new Vector rather than changing a — the same way 1 + 2 doesn't change 1.

A few more

You writePython calls
len(obj)obj.__len__()
obj[i]obj.__getitem__(i)
x in objobj.__contains__(x)
a < ba.__lt__(b)
a * ba.__mul__(b)
A playlist that acts like a list
class Playlist:
    def __init__(self, *songs):
        self.songs = list(songs)

    def __len__(self):
        return len(self.songs)

    def __getitem__(self, i):
        return self.songs[i]

mix = Playlist("Intro", "Groove", "Outro")
print(len(mix))
print(mix[1])
for song in mix:
    print("-", song)
output
3
Groove
- Intro
- Groove
- Outro

Run and edit it in the app.

With __getitem__, a for loop works too — Python asks for item 0, 1, 2… until it gets an IndexError.

Fix the bug: print should show the temperature nicely
class Temperature:
    def __init__(self, degrees):
        self.degrees = degrees

    def str(self):
        return f"{self.degrees}°C"

print(Temperature(21))
output
21°C

Run and edit it in the app.

The method must be named exactly __str__, with two underscores on each side.

What does Python call when it evaluates a + b?

Watch it

Think of it like

Universal plugs. Python's built-ins — print, +, len, for — are sockets in the wall. Dunder methods are the plug on your class that fits them.

Key terms

  • Dunder method — A special method like __add__ that Python calls for built-in syntax.
  • __str__ / __repr__ — The friendly / developer text for an object.
  • Operator overloading — Defining what operators like + mean for your class.

Check yourself

Which method decides what print(obj) shows?

What does len(obj) call?

Should __add__ change self?