Report this

What is the reason for this report?

How To Use the __str__() and __repr__() Methods in Python

Updated on October 8, 2025
How To Use the __str__() and __repr__() Methods in Python

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() untrusted repr; use ast.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 with reprlib; 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:

  1. For str(obj) or print(obj):

    • First tries obj.__str__()
    • If __str__() doesn’t exist, falls back to obj.__repr__()
    • If neither exists, uses the default <class 'ClassName'> representation
  2. For repr(obj) or REPL display:

    • First tries obj.__repr__()
    • If __repr__() doesn’t exist, uses the default <class 'ClassName'> representation

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

Let’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 without print shows repr(mydate).

Key Observations:

  • str() returns a human-readable date format
  • repr() returns a valid Python expression that can recreate the object
  • Design __repr__() to be constructor-like when feasible, but avoid eval() on untrusted text. Use ast.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 displays
  • repr() provides developer-friendly information that can recreate the object
  • print() uses str() 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.

  1. We define a DatabaseRecord class that stores table name, record ID, and data.
  2. The __str__() method provides a simple summary suitable for logs.
  3. 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

Advantages

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)

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; never eval() 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__ so f"{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:

  1. Always implement __repr__() for any non-trivial class
  2. Implement __str__() when you need user-friendly output
  3. Make __repr__() reconstructable when possible
  4. Keep both methods efficient since they’re called frequently
  5. Use f-strings for clean, readable implementations
  6. Test your implementations to ensure they work as expected
  7. Never use eval on repr output — prefer explicit constructors or ast.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:

References

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the author(s)

Pankaj Kumar
Pankaj Kumar
Author
See author profile

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

Andrea Anderson
Andrea Anderson
Editor
Technical Editor
See author profile
Vinayak Baranwal
Vinayak Baranwal
Editor
See author profile

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?

Was this helpful?

This is really helpful article for me…

- vikas shrivastava

Very useful. Thanks.

- Laeeq Khan

Good article. Thanks!

- Parth_Patel

QUOTE: I used str() to create __str__()

- Francisco

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

Thanks for the article!

- Sandro

and hence as you said using: print(str(p)) print(repr(p)) is better than: print(p.__str__()) print(p.__repr__())

- Bhasha

Good articles keep it up!

- Elias

Creative CommonsThis work is licensed under a Creative Commons Attribution-NonCommercial- ShareAlike 4.0 International License.
Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

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.