The difference between __str__ and __repr__

Posted on

In Python, __str__ and __repr__ are special methods used to define how objects are presented as strings, but they serve different purposes. The __str__ method is intended to return a "pretty" or user-friendly string representation of an object, suitable for end-user output. In contrast, __repr__ is meant to provide an "official" string representation of the object that ideally could be used to recreate the object, often more detailed and developer-oriented. By default, the print() function and str() use __str__ if available, while the repr() function and interactive interpreter use __repr__.

Purpose and Use

str Method: The __str__ method aims to provide a readable and understandable string representation of the object for the end user. It is invoked by the str() function and the print() function. If __str__ is not defined, Python falls back to __repr__.

class Example:
    def __str__(self):
        return "This is a user-friendly string representation."

obj = Example()
print(obj)  # Outputs: This is a user-friendly string representation.

repr Method: The __repr__ method is designed to provide a detailed and unambiguous string representation of the object, mainly for debugging and development purposes. It is invoked by the repr() function and the interactive interpreter. The goal is to give a string that can ideally be used to recreate the object.

class Example:
    def __repr__(self):
        return "Example()"

obj = Example()
print(repr(obj))  # Outputs: Example()

Default Behavior

Default repr: If neither __str__ nor __repr__ is defined in a class, Python provides a default implementation of __repr__, which includes the object’s type and memory address.

class Example:
    pass

obj = Example()
print(repr(obj))  # Outputs something like: 

Fallback Mechanism: If __str__ is not defined but __repr__ is, print() and str() will use __repr__ as a fallback.

class Example:
    def __repr__(self):
        return "Example()"

obj = Example()
print(obj)  # Outputs: Example()

Examples and Best Practices

Implementing Both: It is common practice to implement both __str__ and __repr__ to provide clear and useful string representations for different contexts.

class Example:
    def __str__(self):
        return "This is a user-friendly string representation."

    def __repr__(self):
        return "Example()"

obj = Example()
print(str(obj))  # Outputs: This is a user-friendly string representation.
print(repr(obj))  # Outputs: Example()

Detailed repr: The __repr__ method should ideally provide enough detail to understand the object’s state. It often includes the class name and key attributes.

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})"

point = Point(1, 2)
print(repr(point))  # Outputs: Point(x=1, y=2)

When to Use Each

str for User-Facing Output: Use __str__ when you need a clean and readable representation of the object for end-user display.

class User:
    def __init__(self, name, email):
        self.name = name
        self.email = email

    def __str__(self):
        return f"User: {self.name}"

user = User("Alice", "[email protected]")
print(user)  # Outputs: User: Alice

repr for Debugging: Use __repr__ for representations that are helpful in debugging and development. It should be clear and precise, ideally allowing the object to be recreated.

class User:
    def __init__(self, name, email):
        self.name = name
        self.email = email

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

user = User("Alice", "[email protected]")
print(repr(user))  # Outputs: User(name='Alice', email='[email protected]')

Summary

The __str__ and __repr__ methods serve complementary roles. __str__ is for end-user interaction, providing a readable output, while __repr__ is for developers, offering an unambiguous and informative representation of the object. Implementing both in your classes enhances the usability and maintainability of your code, providing clear and context-appropriate string representations for different situations.

Was this helpful?

Thanks for your feedback!