Q&A library Python

What is __repr__ and why should I write one?

Python Intermediate classesdebuggingrepr

Short answer

__repr__ defines how an object appears when printed in a console or inside a list, so a good one makes debugging far easier. Aim for a string that shows the object's key values, ideally one you could paste back in.

The short version

__repr__ controls how your object appears in a console, in a traceback and inside a list. Without it, you see an unhelpful memory address. A good __repr__ shows the values that identify the object, ideally in a form you could paste back into Python to recreate it.

The default is useless

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

print(Point(1, 2))    # <__main__.Point object at 0x7f8b1c0d5e50>
print([Point(1, 2)])  # [<__main__.Point object at 0x7f8b1c0d5e50>]

The memory address tells you nothing. Inside a list of fifty of these, debugging becomes guesswork.

Writing one

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

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

print(Point(1, 2))    # Point(x=1, y=2)
print([Point(1, 2)])  # [Point(x=1, y=2)]

Now the object describes itself wherever it appears, including inside containers, which is exactly where the default fails you.

The guiding rule

Aim for a string that would recreate the object if you pasted it back into Python. That is a useful discipline, because it forces you to include the values that actually define the object and nothing else. When that is impractical (for a large object, say), use angle brackets to signal that it is a description rather than valid code.

def __repr__(self):
    return f"<DataSet rows={len(self.rows)} source={self.source!r}>"

The !r applies repr to the nested value, so strings appear with their quotes, which keeps the output unambiguous.

repr versus str

__repr__ is for developers: unambiguous and detailed. __str__ is for users: readable and friendly. If you define only __repr__, Python uses it for both, which is why writing __repr__ first gives the most benefit for one method.

str(obj)    # uses __str__ if defined, otherwise falls back to __repr__
repr(obj)   # always uses __repr__

For most internal classes, a good __repr__ alone is enough.

Where it pays off

Every debugging session, every log line, every failed test that prints an object. A meaningful repr turns "assertion failed: object at 0x7f8b" into "assertion failed: Point(x=1, y=2)", which is the difference between an immediate diagnosis and ten minutes of poking around.

You get it free with dataclasses

A dataclass generates a sensible __repr__ automatically, showing every field.

from dataclasses import dataclass

@dataclass
class Point:
    x: int
    y: int

print(Point(1, 2))   # Point(x=1, y=2)

This is one of the strongest arguments for using dataclasses for simple record types: you get the useful repr, plus equality, without writing either.

Need this solved on your own data?

The library is free and always will be. When the problem is bigger than an answer, we take on the work.

Start a project