NeuroAgent

Python __str__ vs __repr__: Complete Guide

Learn the key differences between Python's __str__ and __repr__ methods. Discover when to use each, implementation examples, and best practices for creating user-friendly and developer-friendly string representations.

Question

What is the difference between __str__ and __repr__ in Python?

NeuroAgent

__str__ and __repr__ are two special methods in Python that control how objects are represented as strings, but they serve different purposes. __str__ provides a human-readable, informal string representation intended for end users, while __repr__ gives an official, unambiguous representation primarily for developers that should ideally be a valid Python expression that can recreate the object.

Contents

Core Purpose and Usage

The fundamental distinction between these two methods lies in their intended audience and purpose:

  • __str__(): Called by str() and print() functions. It returns a user-friendly, readable string representation meant for display to end users. According to the Python documentation, __str__ provides the “informal” string representation of an object.

  • __repr__(): Called by repr() function and interactive Python shells. It returns an official, unambiguous string representation that should ideally be a valid Python expression. As Stack Overflow explains, repr() returns a string that is a valid Python expression which you can pass to eval() or type directly into Python to recreate the object.

python
>>> class Example:
...     def __init__(self, value):
...         self.value = value
...     def __str__(self):
...         return f"User sees: {self.value}"
...     def __repr__(self):
...         return f"Example({self.value!r})"
...
>>> obj = Example(42)
>>> print(obj)  # Calls __str__
User sees: 42
>>> obj         # Calls __repr__ in interactive shell
Example(42)
>>> str(obj)    # Explicitly calls __str__
'User sees: 42'
>>> repr(obj)   # Explicitly calls __repr__
'Example(42)'

Key Differences Explained

Feature __str__() __repr__()
Primary purpose User-friendly display Developer debugging
Called by print(), str() repr(), interactive shell
Readability Should be easily readable Should be unambiguous
Python expression Not required to be valid Should ideally be evaluable
Fallback behavior Falls back to __repr__ if not defined Uses default object representation
Information level Essential information Complete debugging information

As Real Python explains, __str__ is what you want users to see, while __repr__ is what you want developers to see when debugging.

When to Use Each Method

Use __str__ when:

  • You need a user-friendly string representation for display
  • The output will be shown to end users in logs, UI elements, or reports
  • Readability is more important than technical completeness
  • You want to hide implementation details from users

Use __repr__ when:

  • You need an unambiguous representation for debugging
  • The output might be used in development or testing
  • You want to be able to recreate the object from the string
  • You need complete information about the object’s state

According to DigitalOcean’s tutorial, the best practice is: Always implement a useful __repr__() for any non-trivial class; add __str__() when you need end-user text.

Implementation Examples

Complex Number Example

python
class Complex:
    def __init__(self, real, imag):
        self.real = real
        self.imag = imag
    
    def __str__(self):
        """User-friendly representation"""
        if self.imag == 0:
            return f"{self.real}"
        elif self.real == 0:
            return f"{self.imag}i"
        elif self.imag < 0:
            return f"{self.real} - {-self.imag}i"
        else:
            return f"{self.real} + {self.imag}i"
    
    def __repr__(self):
        """Developer representation - evaluable"""
        return f"Complex({self.real!r}, {self.imag!r})"

# Usage
c = Complex(3, 4)
print(c)           # User sees: 3 + 4i
print(repr(c))     # Developer sees: Complex(3, 4)

Date Object Example

As Python Engineer demonstrates, consider a date class where the representations differ significantly:

python
from datetime import datetime

class CustomDate:
    def __init__(self, year, month, day):
        self.date = datetime(year, month, day)
    
    def __str__(self):
        return self.date.strftime("%B %d, %Y")  # User-friendly: "January 15, 2024"
    
    def __repr__(self):
        return f"CustomDate({self.date.year}, {self.date.month}, {self.date.day})"  # Developer-friendly

# Usage
d = CustomDate(2024, 1, 15)
print(d)           # "January 15, 2024"
d                  # CustomDate(2024, 1, 15)

Best Practices

Implementing __repr__

  1. Always implement __repr__ first - As dbader.org emphasizes, you should always add a __repr__ to your classes because the default implementation for __str__ just calls __repr__ internally.

  2. Make it evaluable - The representation should ideally be a valid Python expression:

    python
    def __repr__(self):
        return f"{self.__class__.__name__}({self.attr1!r}, {self.attr2!r})"
    

    Using !r in f-strings automatically calls repr() on the attributes.

  3. Include complete information - __repr__ should contain all necessary details for debugging purposes.

Implementing __str__

  1. Focus on readability - Make the output easy to understand for end users. As GeeksforGeeks notes, ensure the output is clean and user-friendly.

  2. Consider the context - Format the string appropriately for how it will be displayed.

  3. Handle edge cases - Consider special formatting for different object states.

Common Implementation Pattern

python
class Person:
    def __init__(self, name, age, email):
        self.name = name
        self.age = age
        self.email = email
    
    def __repr__(self):
        # Complete, evaluable representation
        return f"Person({self.name!r}, {self.age!r}, {self.email!r})"
    
    def __str__(self):
        # User-friendly representation
        return f"{self.name}, age {self.age}"

# Usage
p = Person("Alice", 30, "alice@example.com")
print(p)        # Alice, age 30
repr(p)         # Person('Alice', 30, 'alice@example.com')

Common Pitfalls

1. Not Implementing __repr__

Many developers forget to implement __repr__, falling back to the default which shows only the object’s memory address. This makes debugging difficult.

2. Exposing Sensitive Information

Be careful about including sensitive data like passwords or API keys in either representation, especially in __repr__ which might be logged or displayed in error messages. As Real Python warns, “Take extra precautions when implementing these two special methods to ensure that sensitive information, such as user passwords, doesn’t get exposed.”

3. Making __str__ Too Technical

Users shouldn’t need to understand implementation details when reading __str__ output. Keep it simple and user-focused.

4. Incomplete __repr__

If your __repr__ doesn’t include all important attributes, developers won’t be able to fully understand the object’s state from the representation.

5. Circular References

Be careful with circular references when implementing these methods, as they can cause infinite recursion.

python
# Bad example - potential recursion
class Node:
    def __init__(self, value):
        self.value = value
        self.next = None
    
    def __repr__(self):
        return f"Node({self.value}, {self.next})"  # Could cause recursion!

Sources

  1. What is the difference between str and repr? - Stack Overflow
  2. When Should You Use .repr() vs .str() in Python? – Real Python
  3. str() vs repr() in Python - GeeksforGeeks
  4. Difference between str and repr in Python - Python Engineer
  5. How To Use the str() and repr() Methods in Python | DigitalOcean
  6. Python String Conversion 101: Why Every Class Needs a “repr” – dbader.org
  7. Understanding Python’s str and repr Methods: A Guide for Python Developers | Medium

Conclusion

Understanding the difference between __str__ and __repr__ is crucial for writing Pythonic, debuggable code. Remember these key points:

  • __str__ is for users: Make it readable and user-friendly
  • __repr__ is for developers: Make it complete and evaluable
  • Always implement __repr__ first: It provides the foundation for debugging
  • Use __str__ for display: When you need to show information to end users
  • Consider security: Be careful about exposing sensitive information in either method

The best approach is to start with a useful __repr__ implementation that includes all necessary attributes, then add a __str__ method when you need more user-friendly output. This pattern ensures your classes are both developer-friendly and user-friendly.