What is __repr__ in Python?

Discover the __repr__ special method in Python: definition, differences with __str__, practical examples, and best practices for representing your objects.
8 min read
Believemy logo

Definition of __repr__ in Python

__repr__ is a special method (also called a dunder method or magic method) in Python that allows you to define the official representation of an object as a string. Its name comes from the word representation. When you call the built-in repr() function on an object or inspect an object directly in a Python interpreter, it is the __repr__ method that is invoked behind the scenes.

The main goal of __repr__ is to provide an unambiguous representation of the object, ideally precise enough for a developer to recreate the object from that string. If you want to deepen your knowledge of Python and master special methods, we recommend following our comprehensive Python course which covers object-oriented programming in detail.

Good to know

The golden rule: __repr__ is intended for developers, while __str__ is intended for end users. If you can only implement one of the two methods, always choose __repr__.

 

How does __repr__ work?

Every object in Python inherits from the base class object, which provides a default implementation of __repr__. This default implementation returns a string containing the class name and the memory address of the object, which is generally not very useful:

PYTHON
class Car:
    def __init__(self, brand, model):
        self.brand = brand
        self.model = model

my_car = Car("Toyota", "Corolla")
print(repr(my_car))
# Result: <__main__.Car object at 0x7f8b8c0d4a90>

As you can see, this default output tells us nothing about the actual content of the object. That is why it is strongly recommended to define your own __repr__ method in your custom classes.

 

Custom implementation of __repr__

Here is how to properly implement __repr__ for our Car class:

PYTHON
class Car:
    def __init__(self, brand, model, year):
        self.brand = brand
        self.model = model
        self.year = year

    def __repr__(self):
        return f"Car(brand='{self.brand}', model='{self.model}', year={self.year})"

my_car = Car("Toyota", "Corolla", 2023)
print(repr(my_car))
# Result: Car(brand='Toyota', model='Corolla', year=2023)

Notice that we use an f-string here to format the output. The idea is that the returned string should resemble the constructor call that would allow you to recreate the object.

 

Difference between __repr__ and __str__

The distinction between __repr__ and __str__ is a frequent source of confusion for developers. Here is a summary table to clearly understand their differences:

Characteristic__repr____str__
Target audienceDevelopersEnd users
GoalUnambiguous representationReadable representation
Called byrepr(), interactive interpreterstr(), print()
FallbackDefault implementation from objectUses __repr__ if not defined
ConventionShould look like valid Python codeFree format, focused on readability
Warning

Important point: if you define __repr__ but not __str__, Python will automatically use __repr__ as a fallback when calling print or str(). The reverse is not true.

Here is a concrete example illustrating both methods:

PYTHON
class Product:
    def __init__(self, name, price):
        self.name = name
        self.price = price

    def __repr__(self):
        return f"Product(name='{self.name}', price={self.price})"

    def __str__(self):
        return f"{self.name} - ${self.price}"

product = Product("Mechanical Keyboard", 89.99)

# __repr__ is called in the interpreter or via repr()
print(repr(product))  # Product(name='Mechanical Keyboard', price=89.99)

# __str__ is called by print() or str()
print(product)        # Mechanical Keyboard - $89.99

 

When is __repr__ called?

The __repr__ method is invoked in several contexts that you should know about:

1. In the interactive interpreter

When you type the name of an object directly in the Python interpreter (or in a Jupyter notebook), it is __repr__ that is called:

PYTHON
>>> product = Product("Mouse", 49.99)
>>> product
Product(name='Mouse', price=49.99)

 

2. Inside containers (lists, dictionaries, etc.)

When an object is inside a container like a list or a dict, Python uses __repr__ to display it, even if you call print on the container:

PYTHON
products = [
    Product("Keyboard", 89.99),
    Product("Mouse", 49.99),
    Product("Monitor", 299.99)
]

print(products)
# [Product(name='Keyboard', price=89.99), Product(name='Mouse', price=49.99), Product(name='Monitor', price=299.99)]

This is an extremely important behavior to understand: even if your objects have a very readable __str__, it is __repr__ that will be used when they are inside a list or a dictionary.

 

3. With the repr() function

The built-in repr() function directly calls __repr__:

PYTHON
product = Product("Webcam", 59.99)
repr_str = repr(product)
print(repr_str)  # Product(name='Webcam', price=59.99)

 

4. In f-strings with the !r flag

You can force the use of __repr__ in an f-string using the !r flag:

PYTHON
product = Product("Headset", 129.99)
print(f"Debug: {product!r}")
# Debug: Product(name='Headset', price=129.99)

print(f"Display: {product!s}")
# Display: Headset - $129.99

 

Advanced examples

__repr__ with inheritance

When working with class inheritance, it is important to define __repr__ correctly at each level of the hierarchy:

PYTHON
class Animal:
    def __init__(self, name, species):
        self.name = name
        self.species = species

    def __repr__(self):
        return f"Animal(name='{self.name}', species='{self.species}')"

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name, species="Dog")
        self.breed = breed

    def __repr__(self):
        return f"Dog(name='{self.name}', breed='{self.breed}')"

dog = Dog("Rex", "German Shepherd")
print(repr(dog))  # Dog(name='Rex', breed='German Shepherd')

 

__repr__ with dataclasses

dataclass in Python automatically generate a __repr__ method for you, which is one of their great advantages:

PYTHON
from dataclasses import dataclass

@dataclass
class Point:
    x: float
    y: float
    z: float = 0.0

point = Point(1.5, 2.3, 4.0)
print(repr(point))  # Point(x=1.5, y=2.3, z=4.0)

As you can see, the dataclass generates a __repr__ that perfectly follows conventions. You can however disable this behavior with @dataclass(repr=False) if you want to define your own implementation.

 

__repr__ with namedtuples

Similarly, namedtuple automatically provide an informative __repr__:

PYTHON
from collections import namedtuple

Color = namedtuple("Color", ["red", "green", "blue"])
c = Color(255, 128, 0)
print(repr(c))  # Color(red=255, green=128, blue=0)

 

__repr__ and eval()

One of the most important conventions of __repr__ is that, whenever possible, the returned string should be valid Python code that can recreate the object:

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

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

    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

v1 = Vector(3, 4)
v2 = eval(repr(v1))  # Recreates the object from its repr

print(v1 == v2)  # True
print(repr(v2))  # Vector(3, 4)
Warning

Warning: never use eval() on untrusted data in production. This example is purely illustrative of the __repr__ convention.

 

Best practices

Here are the essential rules to follow when implementing __repr__ in your classes:

1. Always implement __repr__

Even if you define __str__, always implement __repr__. It is the most fundamental representation method and serves as a fallback for __str__.

 

2. Return valid Python code if possible

The convention is that __repr__ should return a string that, when passed to eval(), would recreate the object:

PYTHON
# Good practice
def __repr__(self):
    return f"MyClass(param1={self.param1!r}, param2={self.param2!r})"

# Bad practice
def __repr__(self):
    return f"Instance of MyClass"
Good to know

Note the use of !r in the f-string for string attributes. This ensures that quotes are included in the output, making the representation more accurate.

 

3. Use the <...> format when eval() is not possible

If your object is too complex to be recreated via eval(), use the angle bracket convention:

PYTHON
class DatabaseConnection:
    def __init__(self, host, port, database):
        self.host = host
        self.port = port
        self.database = database
        self._connection = None  # Complex internal state

    def __repr__(self):
        return f""

conn = DatabaseConnection("localhost", 5432, "my_app")
print(repr(conn))  # 

 

4. Include essential information

The representation should contain enough information to identify the object and distinguish it from other instances. At a minimum, include the attributes defined in the constructor (__init__ via def).

 

5. Keep the representation concise

Avoid including internal attributes or implementation details that are not relevant for debugging:

PYTHON
# Too verbose
def __repr__(self):
    return (f"User(id={self.id}, name='{self.name}', email='{self.email}', "
            f"created_at={self.created_at}, last_login={self.last_login}, "
            f"login_count={self.login_count}, preferences={self.preferences})")

# Just right
def __repr__(self):
    return f"User(id={self.id}, name='{self.name}', email='{self.email}')"

 

__repr__ for Python built-in types

It is interesting to note that all built-in Python types already implement __repr__ consistently:

PYTHON
# Strings
print(repr("Hello"))         # 'Hello'

# Numbers
print(repr(42))              # 42
print(repr(3.14))            # 3.14

# Lists
print(repr([1, 2, 3]))       # [1, 2, 3]

# Tuples
print(repr((1, 2)))          # (1, 2)

# Dictionaries
print(repr({"a": 1}))        # {'a': 1}

# Sets
print(repr({1, 2, 3}))       # {1, 2, 3}

You will notice that for strings, repr() adds quotes around the value, which clearly distinguishes it from str(). This is particularly useful for debugging when working with tuple, set, or dict.

 

Frequently asked questions

Question

What is the difference between __repr__ and __str__ in Python?

__repr__ provides a technical and unambiguous representation of the object, intended for developers. It should ideally return valid Python code that can recreate the object. __str__, on the other hand, provides a readable and user-friendly representation, intended for end users. If __str__ is not defined, Python uses __repr__ as a fallback. The convention recommends always defining __repr__ first.

 

Question

Should I always implement __repr__ in my classes?

Yes, it is a strongly recommended best practice. Without a custom implementation, Python uses the default representation from object which only displays the class name and memory address, which is not useful for debugging. If you use dataclass or namedtuple, the __repr__ method is automatically generated, saving you from writing it manually.

 

Question

Why is __repr__ used inside lists and dictionaries?

When Python displays the content of a container (list, dict, tuple, etc.), it uses __repr__ and not __str__ for each element. This design choice is explained by the fact that displaying a container is generally intended for debugging, and Python therefore favors the unambiguous representation. This is why it is essential to have an informative __repr__ to properly visualize your objects.

 

Question

How can I learn to master special methods in Python?

Special methods like __repr__, __str__, __init__, or __eq__ are at the heart of object-oriented programming in Python. To master them in depth, we recommend following our dedicated Python course on Believemy, which progressively and practically covers all these essential concepts, from the basics to advanced topics.

Related terms

Discover our python glossary

Browse the terms and definitions most commonly used in development with Python.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.