Magic / Dunder Methods
- Customize object representation with
__repr__and__str__ - Enable arithmetic with
__add__,__mul__,__sub__ - Support comparison with
__eq__,__lt__,functools.total_ordering - Make objects iterable with
__iter__and__next__
Pandas' DataFrame.__getitem__, SQLAlchemy's operator overloading, and pathlib's / operator are all dunder tricks. Staff-level interviews often probe __eq__/__hash__ contracts and the __init__ vs __new__ split — knowing when to override __new__ matters for singletons, immutables, and metaclass work.
- Overriding
__eq__without__hash__— silently makes the class unhashable and breaksset/dictkeys. - Writing
__repr__that isn't a valideval()target — good__repr__should reconstruct the object for debug logs. - Confusing
__str__(human) with__repr__(developer) —print()falls back to__repr__only when__str__is absent.
Python's protocol-based design: every operator and built-in maps to a "dunder" (double-underscore) method.
The ones you'll use most
| Syntax | Method |
|---|---|
len(x) | __len__ |
x[i] | __getitem__ |
for x in y | __iter__ (or __getitem__ as fallback) |
x + y | __add__ |
x == y | __eq__ |
str(x) / print | __str__ then __repr__ |
x() | __call__ |
with x: | __enter__, __exit__ |
The principle
Implement the dunder, get the syntax for free. Your class plugs straight into all of Python.
Try it
- Implement
__eq__onVecsoVec(1,2) == Vec(1,2). - Add
__mul__to scale a vector by a number.
3 graded exercises
Write the code, click Check. We’ll tell you exactly what to fix.
- Exercise 1
Define a class
Bagthat wraps a list of items. Implement__len__(self)returning the count and__contains__(self, item)returning whetheritemis inside. Test:b = Bag([1, 2, 3]); printlen(b)(=3),2 in b(True),9 in b(False). - Exercise 2
Define
Point(x, y)with__eq__(two Points equal when both x and y match) AND__hash__(hash the (x, y) tuple). Test:p1 = Point(1, 2);p2 = Point(1, 2);s = {p1, p2}— the set should have length 1. Printlen(s). - Exercise 3
Define
Vector(x, y)with__add__that returns a newVectorand__repr__returning"Vector(x=1, y=2)"-style. Test:Vector(1, 2) + Vector(3, 4)— print the result. Expected repr containsx=4andy=6.