String Representation: __str__ vs __repr__
15 min · Beginner
Need help? Ask a tutor on WhatsApp (opens in a new tab)When you print an object or inspect it in the terminal, Python looks for special string representation dunder methods. Understanding __repr__ vs __str__ is a hallmark of professional Python developers.
__repr__ for Developers and Debugging
__repr__ is the special method that returns an exact, developer-facing text for an object. repr(obj), the shell, debuggers and containers use it.
__repr__ should provide an unambiguous representation of the object, ideally showing how to recreate it.
class Coordinate: def __init__(self, x, y): self.x = x self.y = y
def __repr__(self): return f"Coordinate(x={self.x}, y={self.y})"
pt = Coordinate(10, 20)print(repr(pt))Example 1 · Why repr shows quotes
class Order: def __init__(self, order_id, status): self.order_id = order_id self.status = status
def __repr__(self): return f"Order({self.order_id!r}, {self.status!r})"
print(Order("A-17", "shipped"))print([Order(18, "pending")])Order('A-17', 'shipped')
[Order(18, 'pending')]What this code does
!rkeeps the quotes around text, so"A-17"and the number18look different.- Inside a list, Python calls
__repr__for every item.
Whenever you inspect an object in the Python interactive shell, debugger, or inside a list [pt], Python invokes __repr__.
__str__ for End Users and Readable Display
__str__ is the special method that returns a readable text for people. print(obj), str(obj) and f-strings use it.
__str__ is intended to be readable and friendly for humans.
class Coordinate: def __init__(self, x, y): self.x = x self.y = y
def __str__(self): return f"({self.x}, {self.y})"
pt = Coordinate(10, 20)print(pt)print(f"Point: {pt}")Example 2 · str for people, repr for logs
class Ticket: def __init__(self, number, title): self.number = number self.title = title
def __str__(self): return f"#{self.number} {self.title}"
def __repr__(self): return f"Ticket({self.number}, {self.title!r})"
t = Ticket(102, "Login fails")print(f"Opened {t}")print(f"Debug: {t!r}")Opened #102 Login fails Debug: Ticket(102, 'Login fails')
What this code does
- A plain f-string field calls
__str__. !rinside the braces asks for__repr__instead.
print(obj) and str(obj) look for __str__ first.
The Fallback Rule
If you only implement one, ALWAYS implement __repr__!
- If
__str__is missing, Python automatically falls back to__repr__. - If
__repr__is missing, Python displays an ugly pointer like<Coordinate object at 0x7fa920>. - Implementing
__repr__guarantees both developer logs andprint()look clean.
Example 3 · The fallback in action
class Account: def __init__(self, owner): self.owner = owner
def __repr__(self): return f"Account({self.owner!r})"
a = Account("Meera")print(a)print(str(a) == repr(a))Account('Meera')
TrueWhat this code does
- No
__str__is defined, soprintuses__repr__. - That is why one good
__repr__already makes logs and output readable.
Summary Comparison
Both methods return a string. They differ in who reads it.
__repr__: Goal is unambiguity for developers and logs. Used byrepr(), debuggers, and collections.__str__: Goal is readability for end users. Used byprint(),str(), and string formatting.
Example 4 · Both methods on one class
class Product: def __init__(self, name, price): self.name = name self.price = price def __repr__(self): return f"Product({self.name!r}, {self.price})" def __str__(self): return f"{self.name} - Rs. {self.price}"
p = Product("Notebook", 75)print("str():", str(p))print("repr():", repr(p))print("in list:", [p])str(): Notebook - Rs. 75
repr(): Product('Notebook', 75)
in list: [Product('Notebook', 75)]What this code does
str(p)uses the user-friendly format.repr(p)uses the explicit constructor-like format.- Objects inside a list
[p]always use__repr__for display.
Next step
Check your understanding
11 quick questions