What's the difference between `__str__` and `__repr__`?

4 minbeginnerfundamentalsdunder-methods

Quick Answer

`__repr__` returns an unambiguous, developer-facing representation (ideally one that could recreate the object) and is used by the REPL, debuggers, and containers (`print([obj])` calls `repr`, not `str`). `__str__` returns a human-readable, user-facing string and is used by `print(obj)`/`str(obj)`. If `__str__` is not defined, Python falls back to `__repr__`.

Detailed Answer

Two different audiences

from datetime import date

d = date(2024, 1, 15)
str(d)    # '2024-01-15'                -- readable
repr(d)   # 'datetime.date(2024, 1, 15)' -- unambiguous, evaluable

__str__ targets end users / logs — readable output. __repr__ targets developers debugging — precise, ideally eval()-able output that makes it unambiguous exactly what the object is.

Defining both on a custom class

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

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

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

p = Point(1, 2)
print(p)          # (1, 2)              -- calls __str__
print(repr(p))    # Point(x=1, y=2)     -- calls __repr__
print([p])        # [Point(x=1, y=2)]   -- containers always use repr()

The fallback rule

If you only define __repr__, str(obj) falls back to calling __repr__ (since object.__str__ calls self.__repr__() by default). So a common shortcut for simple classes is to define only __repr__ and skip __str__ entirely, unless the two representations genuinely need to differ.

Why containers always use repr

print([1, "a", p]) shows [1, 'a', Point(x=1, y=2)] — note the quotes around 'a' and the repr form of p. Lists, dicts, and other containers call repr() on their elements so that nested strings are visibly quoted and distinguishable from the surrounding structure; using str() would make ["a", "b"] print as [a, b], indistinguishable from bare identifiers.

Interview-ready summary: __repr__ is for developers/debugging (unambiguous, ideally eval-able); __str__ is for end users (readable). str() falls back to __repr__ if __str__ isn't defined, and containers always render their elements with repr, never str.