CARVIEW |
- Log in to:
- Community
- DigitalOcean
- Sign up for:
- Community
- DigitalOcean

Introduction
Quick Answer: __str__()
and __repr__()
are Python’s special methods that control how objects are displayed as strings. __str__()
creates user-friendly output for end users, while __repr__()
creates detailed, developer-focused output that ideally can recreate the object.
Understanding these methods is crucial for any Python developer because they affect how your objects appear in:
- User interfaces and reports
- Debugging sessions and error messages
- Logging systems and monitoring tools
- Interactive Python sessions (REPL)
- AI systems and automated workflows
Tested on Python 3.8–3.13; behavior unchanged across these versions.
Why This Matters: Poor string representation leads to confusing error messages, unhelpful debugging sessions, and frustrated users. Well-implemented __str__()
and __repr__()
methods make your code more professional, debuggable, and user-friendly.
Key Takeaways
Before diving deep, here are the essentials:
__str__()
→ Human‑readable output for users (CLI/UI, reports,print()
).__repr__()
→ Developer‑focused, unambiguous output (REPL, tracebacks, debug logs); aim to make it constructor‑like.- Fallback: If
__str__()
is missing, Python falls back to__repr__()
. - Best practice: Always implement a useful
__repr__()
for any non‑trivial class; add__str__()
when you need end‑user text. - Performance: Keep both fast—these are called often; avoid heavy work inside them.
- AI/LLM: Clear, consistent representations improve log readability and model prompts.
- Security: Never
eval()
untrustedrepr
; useast.literal_eval
only for pure literals and prefer explicit constructors for everything else. - MCP/LLM: In MCP servers, use
__str__()
for UI/prompts and__repr__()
for logs/tracebacks; abbreviate large payloads withreprlib
; consider__format__
for stable, LLM‑parsable variants (e.g.,f"{obj:csv}"
).
How Python’s String Representation Methods Work
Quick Answer: Python automatically calls __str__()
when you use print()
, str()
, or string formatting. It calls __repr__()
when you use repr()
, when objects are displayed in the REPL, or when Python needs an unambiguous representation.
The Method Resolution Process
When Python needs to convert an object to a string, it follows this hierarchy:
-
For
str(obj)
orprint(obj)
:- First tries
obj.__str__()
- If
__str__()
doesn’t exist, falls back toobj.__repr__()
- If neither exists, uses the default
<class 'ClassName'>
representation
- First tries
-
For
repr(obj)
or REPL display:- First tries
obj.__repr__()
- If
__repr__()
doesn’t exist, uses the default<class 'ClassName'>
representation
- First tries
When These Methods Are Called
# These trigger __str__()
print(my_object)
str(my_object)
f"Object: {my_object}" # Uses !s conversion
"{0}".format(my_object)
# These trigger __repr__()
repr(my_object)
my_object # In REPL
f"Object: {my_object!r}" # Explicit !r conversion
Note: For details on f-strings, see Python f-strings guide.
Examples of __str__()
and __repr__()
Methods
__str__()
and __repr__()
MethodsLet’s see these methods in action with real examples that demonstrate their practical differences.
Example 1: Built-in datetime
Class
The datetime.datetime
class perfectly demonstrates the difference between __str__()
and __repr__()
:
import datetime
# Create a datetime object
mydate = datetime.datetime(2023, 1, 27, 9, 50, 37, 429078)
# Using str() - calls __str__()
print("str() output:", str(mydate))
print("print() output:", mydate)
# Using repr() - calls __repr__()
print("repr() output:", repr(mydate))
print("REPL output:", mydate) # In REPL, this shows repr()
Output:
str() output: 2023-01-27 09:50:37.429078
print() output: 2023-01-27 09:50:37.429078
repr() output: datetime.datetime(2023, 1, 27, 9, 50, 37, 429078)
REPL output: datetime.datetime(2023, 1, 27, 9, 50, 37, 429078)
Note: In the Python REPL, entering
mydate
withoutrepr(mydate)
.
Key Observations:
str()
returns a human-readable date formatrepr()
returns a valid Python expression that can recreate the object- Design
__repr__()
to be constructor-like when feasible, but avoideval()
on untrusted text. Useast.literal_eval
only for pure literals; for complex objects, prefer explicit constructors.
Example 2: Custom Class Without String Methods
class Product:
def __init__(self, name, price, category):
self.name = name
self.price = price
self.category = category
# Create a product
laptop = Product("MacBook Pro", 1999.99, "Electronics")
print("str() output:", str(laptop))
print("repr() output:", repr(laptop))
Output:
str() output: <__main__.Product object at 0x7f8b8c0d4f40>
repr() output: <__main__.Product object at 0x7f8b8c0d4f40>
Problem: Both return the same unhelpful default representation because neither __str__()
nor __repr__()
is implemented.
Example 3: Custom Class With Both Methods
class Product:
def __init__(self, name, price, category):
self.name = name
self.price = price
self.category = category
def __str__(self):
return f"{self.name} - ${self.price:.2f} ({self.category})"
def __repr__(self):
return f"Product(name='{self.name}', price={self.price}, category='{self.category}')"
# Create a product
laptop = Product("MacBook Pro", 1999.99, "Electronics")
print("str() output:", str(laptop))
print("repr() output:", repr(laptop))
print("print() output:", laptop)
Output:
str() output: MacBook Pro - $1999.99 (Electronics)
repr() output: Product(name='MacBook Pro', price=1999.99, category='Electronics')
print() output: MacBook Pro - $1999.99 (Electronics)
Key Observations:
str()
provides user-friendly information perfect for displaysrepr()
provides developer-friendly information that can recreate the objectprint()
usesstr()
by default
Performance Analysis and Best Practices
Quick Answer: Well-implemented __str__()
and __repr__()
methods improve code readability, debugging experience, and user experience. Poor implementations can hurt performance and create confusion.
In real-world applications, these methods also play a crucial role in areas like logging and monitoring, where clear and informative object representations are essential for troubleshooting and auditing.
Comprehensive Comparison: str()
vs repr()
in Python
This table highlights their differences side by side (see also Advanced Techniques for details on {!r}, {!a}, and custom format).
Aspect | str(obj) |
repr(obj) |
---|---|---|
Intended Audience | End users, CLI output, user-facing logs | Developers, debugging, diagnostic logs |
Primary Usage | print() , str() , f-strings ({obj!s} ), format() |
repr() , REPL, tracebacks, f-strings ({obj!r} ), debugging tools |
Purpose | Human-readable, friendly, concise | Unambiguous, detailed, ideally reconstructable |
Style Guidance | Hide internals, focus on clarity for users | Include class name and key fields, precise and explicit |
Round-Trip Capable? | Not required | Preferably: valid Python expression to recreate the object |
Fallback Behavior | Falls back to __repr__() if __str__() is missing |
Falls back to default <Class at 0x...> if __repr__() is missing |
REPL/Debugger Default | Not shown by default | Shown by default |
Logging | Use for user-facing logs | Use %r /{!r} for diagnostic logs |
f-string Conversion | {obj!s} |
{obj!r} (and {obj!a} for ASCII-escaped) |
Containers | Uses each element’s repr for string conversion |
Same as str ; elements shown via repr |
When to Use Each Method
Use __str__()
when:
- Displaying data to end users in UI or reports
- Creating user-friendly error messages
- Logging information for non-technical stakeholders
- Building CLI applications with user output
Use __repr__()
when:
- Debugging and development work
- Logging detailed diagnostic information
- Working in Python REPL or debugger
- Creating objects that need to be serialized/deserialized
- Building APIs where developers need to understand object structure
Real-World Mapping: Context → Method
Here are some practical contexts and which method to prefer:
- CLI / UI output →
__str__()
(user-friendly display for customers or end-users) - Interactive REPL / shell →
__repr__()
(default in REPL for developer clarity) - Logs for business users →
__str__()
(clear summaries) - Diagnostic / debug logs →
__repr__()
(unambiguous, detailed state) - Error messages / exceptions →
__str__()
(human-readable guidance) - Configuration snapshots / API responses →
__repr__()
(precise state, redact secrets as needed)
Real-World Examples: String with Special Characters
# String with special characters
text = "Hello\nWorld\tTab"
print("str() output:")
print(str(text))
print("\nrepr() output:")
print(repr(text))
Output:
str() output:
Hello
World Tab
repr() output:
'Hello\nWorld\tTab'
Key Observations:
str()
displays the actual formatting (newlines, tabs)repr()
shows the escape sequences (\n
,\t
) for debugging
Example: Container Objects
# List containing different object types
items = [1, "hello", 3.14, [1, 2, 3]]
print("str() output:", str(items))
print("repr() output:", repr(items))
Output:
str() output: [1, 'hello', 3.14, [1, 2, 3]]
repr() output: [1, 'hello', 3.14, [1, 2, 3]]
Note: For containers, both str()
and repr()
use repr()
for each element, which is why they look the same here.
Advanced Techniques
Using f-string Conversions
Python f-strings support conversion flags !s
, !r
, and !a
which explicitly call the str()
, repr()
, and ascii()
functions on the object, respectively:
class Item:
def __init__(self, name):
self.name = name
def __str__(self):
return f"Item: {self.name}"
def __repr__(self):
return f"Item(name='{self.name}')"
item = Item('Widget')
print(f"str: {item!s}") # Calls str(item)
print(f"repr: {item!r}") # Calls repr(item)
print(f"ascii: {item!a}") # Calls ascii(item)
Output:
str: Item: Widget
repr: Item(name='Widget')
ascii: Item(name='Widget')
Dataclasses and Auto-Generated __repr__
Python’s dataclasses
module automatically generates a __repr__()
method:
from dataclasses import dataclass
@dataclass
class Product:
name: str
price: float
category: str
p = Product("Laptop", 999.99, "Electronics")
print("repr() output:", repr(p))
print("str() output:", str(p))
Output:
repr() output: Product(name='Laptop', price=999.99, category='Electronics')
str() output: Product(name='Laptop', price=999.99, category='Electronics')
Note: Since no __str__()
is defined, str()
falls back to __repr__()
.
Custom __format__
for Domain-Specific Specs
You can implement __format__
to support custom formatting codes in f-strings:
class Point:
def __init__(self, x, y):
self.x, self.y = x, y
def __repr__(self):
return f"Point({self.x}, {self.y})"
def __format__(self, spec):
if spec == "csv":
return f"{self.x},{self.y}"
if spec == "poly":
return f"POINT x={self.x} y={self.y}"
return str(self)
p = Point(3, 4)
print(f"{p:csv}") # 3,4
print(f"{p:poly}") # POINT x=3 y=4
Handling Large or Recursive Structures with reprlib
The reprlib
module helps abbreviate long or nested outputs to prevent log spam or recursion errors:
import reprlib
large_list = list(range(10000))
print(reprlib.repr(large_list)) # [0, 1, 2, 3, 4, ... 9999]
This is useful in production when objects can grow very large.
Logging Best Practices with %r
When logging, prefer lazy formatting with %r
to avoid unnecessary string conversions:
import logging
logging.basicConfig(level=logging.DEBUG)
logging.debug("Created %r", p) # Calls __repr__ only if needed
This defers formatting until the log message is emitted.
Security Considerations
While a reconstructable __repr__()
is helpful, never run eval(repr(obj))
on untrusted input. If your __repr__()
returns Python literals, use ast.literal_eval
. For anything else, rely on explicit constructors or serializers instead.
Implementation Examples
Example 1: E-commerce Product Class
Here’s a comprehensive example showing how to implement both methods for a real-world scenario:
class Product:
def __init__(self, name, price, category, in_stock=True):
self.name = name
self.price = price
self.category = category
self.in_stock = in_stock
def __str__(self):
"""User-friendly representation for customers"""
status = "In Stock" if self.in_stock else "Out of Stock"
return f"{self.name} - ${self.price:.2f} ({status})"
def __repr__(self):
"""Developer-friendly representation for debugging"""
return f"Product(name='{self.name}', price={self.price}, category='{self.category}', in_stock={self.in_stock})"
# Usage examples
laptop = Product("MacBook Pro", 1999.99, "Electronics", True)
phone = Product("iPhone", 999.99, "Electronics", False)
print("=== User Display ===")
print(laptop) # Uses __str__()
print(phone) # Uses __str__()
print("\n=== Developer Debug ===")
print(repr(laptop)) # Uses __repr__()
print(repr(phone)) # Uses __repr__()
print("\n=== F-string Examples ===")
print(f"Product: {laptop!s}") # Explicit str()
print(f"Debug: {laptop!r}") # Explicit repr()
Output:
=== User Display ===
MacBook Pro - $1999.99 (In Stock)
iPhone - $999.99 (Out of Stock)
=== Developer Debug ===
Product(name='MacBook Pro', price=1999.99, category='Electronics', in_stock=True)
Product(name='iPhone', price=999.99, category='Electronics', in_stock=False)
=== F-string Examples ===
Product: MacBook Pro - $1999.99 (In Stock)
Debug: Product(name='MacBook Pro', price=1999.99, category='Electronics', in_stock=True)
Example 2: Database Record Class
This example demonstrates how to represent a database record with readable and reconstructable string output.
- We define a
DatabaseRecord
class that stores table name, record ID, and data. - The
__str__()
method provides a simple summary suitable for logs. - The
__repr__()
method outputs detailed reconstruction information for debugging.
import datetime
class DatabaseRecord:
def __init__(self, table_name, record_id, data):
self.table_name = table_name
self.record_id = record_id
self.data = data
self.created_at = datetime.datetime.now()
def __str__(self):
"""Simple summary for logs"""
return f"Record {self.record_id} from {self.table_name}"
def __repr__(self):
"""Complete reconstruction info"""
return f"DatabaseRecord(table_name='{self.table_name}', record_id={self.record_id}, data={self.data!r}, created_at=datetime.datetime({self.created_at.year}, {self.created_at.month}, {self.created_at.day}, {self.created_at.hour}, {self.created_at.minute}, {self.created_at.second}, {self.created_at.microsecond}))"
# Usage
record = DatabaseRecord("users", 123, {"name": "John", "email": "john@example.com"})
print("Log entry:", str(record))
print("Debug info:", repr(record))
Example 3: Configuration Class
class Config:
def __init__(self, **kwargs):
self.settings = kwargs
def __str__(self):
"""User-friendly config summary"""
return f"Configuration with {len(self.settings)} settings"
def __repr__(self):
"""Exact reconstruction"""
return f"Config({', '.join(f'{k}={v!r}' for k, v in self.settings.items())})"
# Usage
config = Config(debug=True, port=8080, host="localhost")
print("Config:", str(config))
print("Debug:", repr(config))
Troubleshooting Common Issues
Issue 1: Both Methods Return the Same Value
Problem: str()
and repr()
return identical output.
Cause: Only __repr__()
is implemented, so str()
falls back to it.
Solution: Implement both methods with different purposes:
class BadExample:
def __repr__(self):
return "BadExample()"
# This will show the same for both str() and repr()
obj = BadExample()
print(str(obj)) # BadExample()
print(repr(obj)) # BadExample()
class GoodExample:
def __str__(self):
return "User-friendly display"
def __repr__(self):
return "GoodExample()"
obj = GoodExample()
print(str(obj)) # User-friendly display
print(repr(obj)) # GoodExample()
Issue 2: __repr__()
Not Reconstructable
Problem: repr()
output can’t be used to recreate the object.
Solution: Make __repr__()
return valid Python code:
class BadRepr:
def __repr__(self):
return f"BadRepr with value {self.value}" # Not reconstructable
class GoodRepr:
def __init__(self, value):
self.value = value
def __repr__(self):
return f"GoodRepr({self.value!r})" # Reconstructable
# Test reconstruction
obj = GoodRepr("test")
code = repr(obj) # "GoodRepr('test')" — constructor-like for humans/debuggers
reconstructed = GoodRepr(obj.value) # re-create explicitly from known fields
print(f"Original: {obj}")
print(f"Reconstructed: {reconstructed}")
print(f"Equal: {obj.value == reconstructed.value}")
Security note: Never use eval(repr(obj))
on untrusted text. If (and only if) your __repr__()
returns pure Python literals (lists, dicts, numbers, strings), you may use ast.literal_eval
to parse them; otherwise prefer explicit constructors or safe serializers.
Issue 3: Performance Issues
Problem: String methods are called frequently and slow down your application.
Solution: Cache expensive computations and keep methods simple:
class OptimizedClass:
def __init__(self, data):
self.data = data
self._str_cache = None
self._repr_cache = None
def __str__(self):
if self._str_cache is None:
# Expensive computation only once
self._str_cache = f"Processed: {self._expensive_processing()}"
return self._str_cache
def __repr__(self):
if self._repr_cache is None:
self._repr_cache = f"OptimizedClass({self.data!r})"
return self._repr_cache
def _expensive_processing(self):
# Simulate expensive operation
return "".join(str(x) for x in self.data)
Advantages and Disadvantages of the __str__()
and __repr__()
Methods in Python
__str__()
and __repr__()
Methods in PythonAdvantages
1. Improved User Experience
- Clear, readable output for end users
- Professional appearance in applications
- Better error messages and logging
2. Enhanced Debugging
- Detailed object information for developers
- Easy object reconstruction for testing
- Better traceback information
3. AI and Automation Benefits
- Clear object representations help AI systems understand data
- Better serialization/deserialization support
- Improved API documentation and introspection
4. Performance Benefits
- Cached string representations can improve performance
- Reduced memory usage with lazy evaluation
- Better integration with Python’s built-in functions
Disadvantages
1. Implementation Overhead
- Requires additional code for each class
- Can increase class complexity
- Need to maintain both methods consistently
2. Performance Considerations
- String methods are called frequently
- Poor implementations can slow down applications
- Memory usage for cached representations
3. Maintenance Burden
- Need to update methods when class structure changes
- Risk of inconsistencies between
__str__()
and__repr__()
- Testing complexity increases
Using __str__()
and __repr__()
in MCP Servers (LLM/Agent Context)
__str__()
and __repr__()
in MCP Servers (LLM/Agent Context)When you build AI-facing backends using the Model Context Protocol (MCP) Python SDK, clear string representations supercharge both developer ergonomics and LLM reliability.
Why this matters in MCP
- LLM outputs & logs: MCP tools/resources frequently surface objects through logs or fall back text; a principled
__repr__()
yields unambiguous traces, while__str__()
gives human-friendly summaries. - Structured vs. unstructured: MCP tools often return structured data (Pydantic/TypedDict/dataclass). If a client prints the object—or an LLM quotes it—your
__str__()
/__repr__()
decide how it reads. - Fewer heisenbugs: Constructor-style
__repr__()
makes reproducing issues from agent logs straightforward.
Quickstart context (FastMCP + representations)
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("Demo Server")
class CalculatorResult:
def __init__(self, a, b, total):
self.a = a
self.b = b
self.total = total
def __str__(self):
# User-friendly for dashboards / human-readable logs
return f"{self.a} + {self.b} = {self.total}"
def __repr__(self):
# Developer-focused, constructor-like (no secrets)
return f"CalculatorResult(a={self.a}, b={self.b}, total={self.total})"
@mcp.tool()
def add(a: int, b: int) -> CalculatorResult:
"""Add two numbers with human/AI-friendly representation."""
return CalculatorResult(a, b, a + b)
Operational tips
- Use logging’s lazy formatting:
logging.debug("tool result %r", result)
. - Keep
__repr__()
constructor-like where feasible; nevereval()
untrusted text (see security note above). - For large payloads, abbreviate with
reprlib.repr()
to keep agent logs compact. - If you expose custom formats to LLM prompts (e.g.,
:csv
,:poly
), implement__format__
sof"{obj:csv}"
is stable and parseable.
Learn more: The SDK, examples, and transports (stdio, SSE, Streamable HTTP) are documented at the MCP Python SDK repo.
Frequently Asked Questions
Q: What is the difference between __str__()
and __repr__()
in Python?
A: __str__()
returns a human-readable string for end users, while __repr__()
returns a detailed, developer-friendly string that ideally can recreate the object. __str__()
is used by print()
, str()
, and string formatting, while __repr__()
is used by repr()
, the REPL, and debugging tools.
Q: Is __str__()
required in every Python class?
A: No, __str__()
is not required. If you don’t implement it, Python will fall back to __repr__()
. However, implementing both methods provides better user experience and debugging capabilities.
Q: What happens if you don’t define __repr__()
in a class?
A: If __repr__()
is not defined, Python uses the default representation: <class 'ClassName'>
or <class 'ClassName'> object at 0x...
. This provides no useful information about the object’s state.
Q: Can __str__()
and __repr__()
return the same value?
A: Yes, they can return the same value, but it’s generally not recommended. __str__()
should be user-friendly, while __repr__()
should be developer-focused and ideally reconstructable.
Q: When should you use __repr__()
instead of __str__()
?
A: Use __repr__()
for debugging, logging diagnostic information, working in the REPL, or when you need an unambiguous representation that can recreate the object. Use __str__()
for user-facing displays, reports, and UI output.
Q: Why does Python print the __repr__()
of an object in the shell?
A: In the Python REPL (interactive shell), objects are displayed using __repr__()
because it provides more detailed, developer-friendly information. This helps developers understand the object’s structure and state during interactive sessions.
Q: How do I make __repr__()
reconstructable?
A: Make __repr__()
return a string that looks like a valid Python expression to recreate the object. For example: return f"ClassName({self.attr!r})"
instead of return f"ClassName with attr {self.attr}"
.
Q: Can I use f-strings in __str__()
and __repr__()
methods?
A: Yes, f-strings are perfectly fine and often preferred for their readability and performance. Just be careful with quotes and escaping when creating reconstructable __repr__()
output.
Q: What’s the performance impact of these methods?
A: These methods are called frequently, so they should be efficient. Avoid expensive computations in these methods, and consider caching if needed. Simple string formatting is usually fast enough.
Q: How do these methods work with inheritance?
A: Both methods follow normal inheritance rules. Child classes can override them, and you can call the parent’s method using super().__str__()
or super().__repr__()
. Be careful to maintain the expected behavior when overriding.
Q: How do __str__()
and __repr__()
impact MCP/LLM agent reliability?
A: In MCP pipelines, tools and resources often surface objects in logs and model-visible text. A concise __str__()
keeps prompts/UI readable, while an unambiguous, constructor-style __repr__()
makes traces reproducible and debugging deterministic. Avoid secrets in __repr__()
, use lazy logging (logging.debug("Created %r", obj)
), abbreviate large payloads with reprlib.repr()
, and if you need a machine-stable shape in prompts, expose __format__
(e.g., f"{obj:csv}"
) or return structured data instead of free text.
Conclusion
Understanding and properly implementing __str__()
and __repr__()
methods is essential for writing professional Python code. These methods control how your objects are displayed to both users and developers, affecting everything from user experience to debugging efficiency.
Key Points to Remember:
- Always implement
__repr__()
for any non-trivial class - Implement
__str__()
when you need user-friendly output - Make
__repr__()
reconstructable when possible - Keep both methods efficient since they’re called frequently
- Use f-strings for clean, readable implementations
- Test your implementations to ensure they work as expected
- Never use
eval
onrepr
output — prefer explicit constructors orast.literal_eval
for pure literals.
By following these best practices, you’ll create more maintainable, debuggable, and user-friendly Python applications. The investment in proper string representation methods pays dividends throughout the development lifecycle.
Further Learning
To deepen your understanding of Python’s string representation methods and related concepts:
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
About the author(s)
Java and Python Developer for 20+ years, Open Source Enthusiast, Founder of https://www.askpython.com/, https://www.linuxfordevices.com/, and JournalDev.com (acquired by DigitalOcean). Passionate about writing technical articles and sharing knowledge with others. Love Java, Python, Unix and related technologies. Follow my X @PankajWebDev
Building future-ready infrastructure with Linux, Cloud, and DevOps. Full Stack Developer & System Administrator @ DigitalOcean | GitHub Contributor | Passionate about Docker, PostgreSQL, and Open Source | Exploring NLP & AI-TensorFlow | Nailed over 50+ deployments across production environments.
Still looking for an answer?
Who is responsible for calling the __repr__() and __str__()
- Shashikant Thakur
Hi Pankaj - I still dont understand the difference between the __str__ and __repr__. From your notes you mentioned Python __repr__() function returns the object representation. It could be any valid python expression such as tuple, dictionary, string etc, whereas __str__() represent string representation of the Object. I tried added an expression (return “{firstName:” + self.fname + “, lastName:” + self.lname + “, age:” + str(self.age) + “}”) in __str__() method and returned it to main function, it didnt throw any error. When both __str__() and __repr__() can return only strings or string expressions i am not sure what exactly is the difference. Any inputs would be helpful
- jagan
Sorry, but this is an awful article. The difference between __repr__ and __str__ is that __repr__ is meant for developers (eg. debugging) and __str__ is used for users. You didn’t explain this simple difference and instead wrote many very or slightly wrong things - You write in the summary “__str__ must return string object whereas __repr__ can return any python expression.” which is wrong! - __repr__ needs to return string as well, as you showed earlier! You use class variables and override them with instance variable, why? thats just not needed and beginners will think it is needed (perhaps you think its necessary?) You call the dunder methods directly (eg `p.__str__()`) instead of using the proper builtins (`str(p)` and `repr(p)`) You use camelCase arguments when the python style is snake_case (underscores) You write there is no fallback for missing __repr__ but you clearly show the fallback (Python shows the type and id in hex). Not having a fallback would be something like raising NotImplementedError. There is a convention (but not really necessary) to have repr return a *string* that looks like the constructor for the object, so one can copy paste the repr outout to get identical copy. eg. a proper example would be: ``` class Person: def __init__(name, age): self.name = name self.age = age def __repr__(self): return f"““Person(name=”{self.name}”, age={self.age})“”" # developer friendly def __str__(self): return f"{self.name} is {self.age} years old" # use friendly ``` I don’t normally bash random people for being wrong, but this article is at the top of the Google search results for repr vs str in python, and a lot of beginners will read this.
- Iftah
and hence as you said using: print(str(p)) print(repr(p)) is better than: print(p.__str__()) print(p.__repr__())
- Bhasha
- Table of contents
- Introduction
- Key Takeaways
- How Python's String Representation Methods Work
- Examples of `__str__()` and `__repr__()` Methods
- Performance Analysis and Best Practices
- Advanced Techniques
- Implementation Examples
- Troubleshooting Common Issues
- Advantages and Disadvantages of the `__str__()` and `__repr__()` Methods in Python
- Using `__str__()` and `__repr__()` in MCP Servers (LLM/Agent Context)
- Frequently Asked Questions
- Conclusion
- Further Learning
- References
Deploy on DigitalOcean
Click below to sign up for DigitalOcean's virtual machines, Databases, and AIML products.
Become a contributor for community
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
DigitalOcean Documentation
Full documentation for every DigitalOcean product.
Resources for startups and SMBs
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Get our newsletter
Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.
New accounts only. By submitting your email you agree to our Privacy Policy
The developer cloud
Scale up as you grow — whether you're running one virtual machine or ten thousand.
Get started for free
Sign up and get $200 in credit for your first 60 days with DigitalOcean.*
*This promotional offer applies to new accounts only.