What is the difference between __str__ and __repr__ in Python?
__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
- Key Differences Explained
- When to Use Each Method
- Implementation Examples
- Best Practices
- Common Pitfalls
Core Purpose and Usage
The fundamental distinction between these two methods lies in their intended audience and purpose:
-
__str__(): Called bystr()andprint()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 byrepr()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 toeval()or type directly into Python to recreate the object.
>>> 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
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:
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__
-
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. -
Make it evaluable - The representation should ideally be a valid Python expression:
pythondef __repr__(self): return f"{self.__class__.__name__}({self.attr1!r}, {self.attr2!r})"Using
!rin f-strings automatically callsrepr()on the attributes. -
Include complete information -
__repr__should contain all necessary details for debugging purposes.
Implementing __str__
-
Focus on readability - Make the output easy to understand for end users. As GeeksforGeeks notes, ensure the output is clean and user-friendly.
-
Consider the context - Format the string appropriately for how it will be displayed.
-
Handle edge cases - Consider special formatting for different object states.
Common Implementation Pattern
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.
# 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
- What is the difference between str and repr? - Stack Overflow
- When Should You Use .repr() vs .str() in Python? – Real Python
- str() vs repr() in Python - GeeksforGeeks
- Difference between str and repr in Python - Python Engineer
- How To Use the str() and repr() Methods in Python | DigitalOcean
- Python String Conversion 101: Why Every Class Needs a “repr” – dbader.org
- 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.