__str__ vs __repr__
Overview
Python uses two main dunder methods (special methods starting and ending with double underscores) to convert objects to strings: `__str__` for readable output and `__repr__` for unambiguous developer representations. By default, both print `<__main__.MyClass object at 0x...>`, but overriding them gives meaningful descriptions. Think of `__str__` as the 'display name' for a user and `__repr__` as the 'technical ID card' for a developer.
It solves the problem of opaque object representations. Clear string representations make logging, debugging, and user interfaces significantly easier by avoiding memory addresses in terminal output.
Where used: Logging configuration, Pydantic error messages, REPL debugging
Why learn this
- Makes debugging faster by displaying object state instead of memory addresses in the REPL.
- Allows custom string formatting in logging or UI without writing extra `to_string()` methods.
Code walkthrough
class Config:
def __init__(self, env):
self.env = env
def __repr__(self):
return f'Config(env={self.env!r})'
c = Config('prod')
print(c)
print([c])
Focus: print([c])
Aha moment
class Task:
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
t = Task('build')
print([t])
Prediction: What does this print?
Common guess: ['build']
Collections like lists always use `__repr__` to format their elements, even if you print the list using `str()`. Since `Task` lacks a `__repr__`, you get the default memory address.
Common mistakes
- Implementing only __str__: If you only implement `__str__`, collections like lists or dicts will still use `__repr__` when printed, showing memory addresses. Fix: Implement `__repr__` first; Python uses it as a fallback for `__str__`.
Glossary
- unambiguous
- Clear and exact, leaving no doubt about what something is or what it means. Example: `User(name='Alice', role='admin')`.
- REPL
- Read-Eval-Print Loop; an interactive programming environment where you can type commands and see the results immediately. Example: `repr(obj)`.
Recall questions
- What is the primary difference in purpose between `__str__` and `__repr__`?
- If an object only implements `__repr__`, what happens when you call `str(obj)`?
Understanding checks
What does this code output?
Box()
When `__str__` is not explicitly defined, Python falls back to calling the object's `__repr__` method.
Why is it important to implement `__repr__` for an object instead of only `__str__`?
Because collections like lists and dictionaries use `__repr__` to display their elements, even if you print them using `str()`.
If you only implement `__str__`, printing a list of your objects will still show unhelpful memory addresses.
Practice tasks
Basic User Representation
Create a `User` class with `name` and `role` attributes. Implement `__repr__` to return a string like `User(name='Alice', role='admin')` and `__str__` to return `Alice (admin)`.
Challenge
Logging Context
Write an `APIRequest` class taking `method` and `url`. Implement `__repr__` so that logging a list of requests shows them clearly as `APIRequest(method='GET', url='/users')`. Do not implement `__str__`.