Mastery
Mastery/Python/D. Classes & OOP internals
T1 · high-leverage

__repr__ vs __str__, and why every class should define __repr__

repr() is the unambiguous, developer-facing representation (ideally eval-able); str() is the human-facing one. str() falls back to __repr__ if __str__ isn't defined, but the reverse is never true. The detail that trips people up: containers (list, dict, ...) always use each element's __repr__ when printed -- even if the element defines a nicer __str__ -- because a container's own __str__/__repr__ are the same and both call repr() on their contents for unambiguity.

python
class Point:
    def __init__(self, x, y):
        self.x, self.y = x, y
    def __repr__(self):
        return f"Point({self.x!r}, {self.y!r})"

p = Point(1, 2)
print("str(p) with no __str__ defined -> falls back to __repr__:", str(p))
print("a list of p uses __repr__ regardless:", [p])

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

p2 = PointWithStr(1, 2)
print("str(p2) now uses the custom __str__:", str(p2))
print("...but inside a list, STILL __repr__, not __str__:", [p2])

Interview angle

A quick, high-signal question: "why does every class you write need __repr__?" A candidate who says "for debugging" is half right; the fuller answer is that __repr__ is the fallback for __str__, the representation used inside containers, and what shows up in a debugger/REPL/traceback by default — so skipping it means every one of those contexts prints an unhelpful <__main__.Foo object at 0x...>.

In the industry

Style guides (Google's Python style guide among them) explicitly require __repr__ on any class intended for reuse, precisely because debugging a collection of objects with no __repr__ means staring at memory addresses. It's one of the cheapest, highest-value additions to any class, and its absence is a near-universal first comment on a new class in code review at teams that care about debuggability.