Quick answer: repr(obj) asks an object for a developer-facing representation, normally through __repr__(). Use it in debugging, logs, and containers when identity or state matters. A useful __repr__ is concise, deterministic, and safe to call; it is not automatically an executable expression.

repr() returns developer-facing text for an object. It is meant to reveal detail that helps during debugging, logging, testing, and inspection.
The official Python repr documentation describes the built-in function. The data model pages explain object.__repr__() and object.__str__().
Use repr() when exact detail matters. Use str() when the output is meant for a human reader. Many built-in objects make this difference easy to see because repr() keeps quotes, escapes, and structural clues.
That makes repr() especially useful at the boundary between code and diagnosis. When an object behaves unexpectedly, the representation should answer basic questions quickly: what type is this, what state does it carry, and why did it reach this branch?
See The Difference Between repr And str
Strings with whitespace or escape characters show why repr() is useful.
text = "Python\nPool"
print(str(text))
print(repr(text))
str(text) prints the line break as an actual line break. repr(text) shows \n, so the hidden character is visible in the output.
This is helpful when a value looks correct on screen but still fails a comparison, parser, or test.
The same idea applies to tabs, trailing spaces, carriage returns, and empty strings. A direct print call can make those cases look identical, but repr() keeps the clues visible.
Use repr In Debug Output
When printing several values for inspection, repr() makes empty strings, spaces, and newline characters easier to spot.
items = ["apple", "", " pear ", "orange\n"]
for item in items:
print(f"raw={repr(item)} length={len(item)}")
The result shows which item is empty, which item has surrounding spaces, and which item includes a newline. Plain printing would hide much of that detail.
This pattern is useful in small scripts and temporary diagnostics. For long-running applications, send the same kind of output through a logger.
Keep debug messages compact. A short representation beside a length, identifier, or status flag is usually more useful than dumping a huge object without context.
Define __repr__ For A Class
Custom classes can define __repr__(). The method should return a string that identifies the object clearly.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Point(x={self.x!r}, y={self.y!r})"
point = Point(3, 5)
print(repr(point))
The !r conversion inside the f-string calls repr() on each field. That keeps nested strings, numbers, and other objects displayed in a developer-friendly form.
A useful __repr__() includes the class name and the important state needed to understand the object.
Try to make the output stable across runs. If the object has a timestamp, random identifier, or large cached payload, include it only when it explains the current problem.

Add __str__ For Friendly Text
__repr__() and __str__() can return different text. Use __str__() for a friendly display and keep __repr__() for inspection.
class Account:
def __init__(self, owner, balance):
self.owner = owner
self.balance = balance
def __repr__(self):
return f"Account(owner={self.owner!r}, balance={self.balance!r})"
def __str__(self):
return f"{self.owner}: ${self.balance:.2f}"
account = Account("Maya", 42.5)
print(str(account))
print(repr(account))
Printing the object uses __str__(). Calling repr() uses __repr__(). If __str__() is missing, Python can fall back to __repr__().
Keeping both methods separate lets user-facing screens stay clean while debug output remains precise.
This separation also helps tests. Friendly text can change for wording or formatting reasons, while representation text can stay focused on the object’s state.
Use !r In F-Strings
F-strings support !r as a shorthand for repr(). It is compact and readable inside diagnostic messages.
name = " Ada "
score = 98
print(f"name={name!r}")
print(f"score={score!r}")
The first line shows the spaces around the name because !r uses the representation form. This is often the easiest way to expose unwanted whitespace in text data.
Use !r when building quick debug strings, assertions, or error messages that need to show the exact value.
For larger messages, combine !r with field names so the output remains readable. A line such as name=' Ada ' is easier to scan than a sequence of raw values.

Round Trip Simple Literals
For some built-in literal values, repr() returns text that Python can parse back with ast.literal_eval().
import ast
data = {"name": "Ada", "scores": [9, 10]}
text = repr(data)
restored = ast.literal_eval(text)
print(text)
print(restored == data)
This works for safe literal structures such as strings, numbers, lists, tuples, dictionaries, booleans, and None. It is not a general serialization format for every object.
For application data, prefer JSON, CSV, a database, or another explicit format. Treat repr() primarily as inspection output.
Round-tripping is a convenience for simple literals, not a promise for every custom object. If code must save and load data reliably, choose a format with a documented schema.
Practical Guidelines
A good __repr__() is short, unambiguous, and stable enough to help diagnose problems. It should not perform slow work, network calls, or operations with side effects.
Do not put secrets into __repr__(). Objects that hold tokens, passwords, or private identifiers should mask those fields before returning debug text.
Use repr() in tests when failure messages need exact details. Seeing quotes, escapes, and empty strings usually makes mismatches faster to understand.
The practical rule is simple: use str() for friendly output, use repr() for exact inspection, and implement __repr__() on custom classes so debug output shows the object’s meaningful state.
Use repr() At Debugging Boundaries
repr() makes strings, containers, and custom objects easier to distinguish in a debugger or diagnostic message. It commonly exposes quotes, escape sequences, and type-relevant details that str() may intentionally omit for readability.

Implement __repr__ For Useful State
A class representation should identify the class and include the small set of fields that helps diagnose it. Avoid dumping secrets, huge payloads, unstable memory addresses, or work that can fail during logging. Keep the method side-effect free.
Understand str() And __str__
str() is the readable presentation hook and repr() is the developer representation hook. If __str__ is absent, Python can fall back to __repr__, but a custom __repr__ should remain useful even when no friendly display method exists.

Represent Objects Inside Containers
Lists, tuples, sets, and dictionaries generally use repr() for their members. This is why a good __repr__ improves an entire debugging output rather than only a direct print or repr call.
Do Not Assume eval() Safety
Some built-in repr strings resemble valid Python expressions, but the protocol does not require that every representation be reconstructable. Never eval() untrusted or arbitrary repr output; use a deliberate serializer for data interchange.
Test Representation Contracts
Test the important fields, stable formatting, empty values, nested objects, and sensitive fields. If logs or snapshots depend on the text, treat changes to __repr__ as an observable contract and review them deliberately.
The official repr() documentation and object.__repr__ data model reference define the representation protocol. Related guidance includes logging and Python data types.
For related representation boundaries, compare safe logging, Python object types, and representation tests when designing a custom class.
Frequently Asked Questions
What does repr() do in Python?
repr() returns a developer-oriented string representation of an object by calling its __repr__ method or a type’s default representation.
What is the difference between str() and repr()?
str() aims for readable user-facing output, while repr() aims for an informative developer-facing representation that helps identify the object and its state.
How do I write a custom __repr__ method?
Define __repr__(self) on the class and return a string; it should be concise, informative, and safe to call while debugging.
Does repr() always produce a string that eval() can parse?
No. Some built-in representations are evaluable, but custom or external objects are not required to produce executable Python expressions.