python1class Coins:2 def __init__(self, n):3 self.n = n4 def __add__(self, o):5 return Coins(self.n + o.n)6 def __repr__(self):7 return f"Coins({self.n})"8a = Coins(3)9b = Coins(4)10c = a + b11print(c)Coins(3)n = 3Coins(4)a + bCoins(7)Coins(7)
Code card: coins.py; the highlighted lines are the ones runningPython interpreter: the bubble shows the special method it callsTerminal: where print() writesObject boxes: a, b and c, each with its own attribute nSpecial (dunder) methods are methods whose names start and end with two underscores. You write ordinary syntax and Python calls them for you. Each step lights the parts it is about. A token hops along the step's arrow, and when syntax reaches the interpreter a bubble shows the call Python makes instead: Coins(3) becomes obj.__init__(3), a + b becomes a.__add__(b), print(c) becomes c.__repr__(). In the last two steps a method's lines fade away: without __repr__ the output falls back to a default, and without __add__ the + stops with a TypeError.

Meet the dunders

  1. Methods named with two underscores on each side, like __init__, are special methods, or dunder methods (double underscore). You rarely call them yourself: Python calls them for you when you write Coins(3), a + b or print(c).

Coins at work

Take one away

Try it yourself

;; step 1/9
# a special method has two underscores on each side:
__init__   __add__   __repr__   __len__   __eq__

# you write ordinary syntax ...
len(x)      x + y      print(x)
# ... and Python calls the special method:
x.__len__() x.__add__(y) x.__str__()

Strictly, Python looks the special method up on the class, not on the object: a + b runs type(a).__add__(a, b). If that is missing (or returns NotImplemented) and b is of a different type, Python tries type(b).__radd__(b, a) before raising TypeError. For two Coins, __radd__ is never tried. The figure shortens the traceback (it leaves out the File line and the ~~^~~ marker) and wraps the long TypeError line to fit its small terminal; the Try it panel shows the full text. $ is the terminal's own prompt.