Tutorial

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

Concise guide: python __str__ vs __repr__ — what each does, when Python calls them, examples, best practices (constructor-like repr, user-friendly str), f-strings, dataclasses, reprlib, logging, and troubleshooting.

Drake Nguyen

Founder · System Architect

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

Introduction

Quick answer: python __str__ vs __repr__ control an object's string representation. Implementing __str__() produces readable output for end users, while __repr__() should give an unambiguous, developer-oriented string—ideally one that can be used to recreate the object.

These python dunder methods affect printouts, REPL displays, logging, and debugging. Good implementations make debugging easier and improve how objects appear in user interfaces and logs.

Key takeaways

  • __str__() → human-friendly text (used by print() and str()).
  • __repr__() → machine/developer-focused text (used by repr(), REPL, and diagnostic logs).
  • If __str__() is absent, Python falls back to __repr__().
  • Prefer a useful __repr__() for non-trivial classes; add __str__() when you need nicer user output.
  • Keep both methods fast—these python special methods are called frequently.

How python's string representation methods work

When Python converts an object to text it follows a simple resolution order:

  • str(obj) and print(obj) try obj.__str__() first; if missing they use obj.__repr__().
  • repr(obj) and the interactive shell use obj.__repr__().

Common triggers

# triggers __str__
print(obj)
str(obj)
f"Value: {obj}"        # calls __str__ (or !s)

# triggers __repr__
repr(obj)
obj                       # REPL shows repr()
f"Value: {obj!r}"       # explicit !r

Note: f-string conversion flags !s, !r, and !a call str(), repr(), and ascii() respectively.

Examples: __str__ python vs __repr__ python

Built-in datetime example

import datetime
d = datetime.datetime(2024, 2, 1, 12, 30)
print(str(d))   # human readable
print(repr(d))  # constructor-like: datetime.datetime(2024, 2, 1, 12, 30)

Here str() shows a readable timestamp while repr() returns a reconstructable expression.

Custom class examples

class Product:
    def __init__(self, name, price):
        self.name = name
        self.price = price

    def __str__(self):
        return f"{self.name} — ${self.price:.2f}"

    def __repr__(self):
        return f"Product(name={self.name!r}, price={self.price!r})"

p = Product('Coffee', 3.5)
print(p)         # uses __str__ for user-friendly output
print(repr(p))   # uses __repr__ for debugging

How containers and dataclasses behave

Container objects (lists, dicts) and dataclasses use element repr() when converting to strings. The dataclasses module auto-generates a __repr__(), so str() falls back to that unless you override it.

Advanced techniques

Custom __format__ for domain-specific representation

class Point:
    def __init__(self, x, y):
        self.x, self.y = x, y
    def __repr__(self):
        return f"Point({self.x!r}, {self.y!r})"
    def __format__(self, spec):
        if spec == 'csv':
            return f"{self.x},{self.y}"
        return str(self)

p = Point(3, 4)
print(f"{p:csv}")  # prints 3,4

Abbreviating large outputs with reprlib

import reprlib
big = list(range(10000))
print(reprlib.repr(big))  # abbreviated, avoids log spam

Logging and repr() vs str()

For diagnostic logs prefer %r or {!r} so logging defers conversion until needed and uses __repr__():

import logging
logging.basicConfig(level=logging.DEBUG)
logging.debug('Created: %r', p)

Best practices and python datamodel __repr__ guidance

  • Make __repr__() informative and, when sensible, constructor-like: e.g. ClassName(field=...).
  • Use __str__() for short, user-friendly displays and UIs.
  • Never call eval() on untrusted repr() output; if the repr returns pure literals use ast.literal_eval.
  • Avoid heavy computations inside these python special methods; cache results if needed.
  • Redact secrets: logs and __repr__() can leak data.

Troubleshooting common issues

Both methods show the same text

Cause: only __repr__() implemented so str() falls back. Solution: implement both with different intent.

repr not reconstructable

If __repr__() does not look like a valid constructor-call, it won’t round-trip. Return a string like ClassName(field1=value1!r, ...) when possible.

Performance concerns

These methods are invoked frequently (logs, formatting). Keep them lightweight; compute heavy values lazily and cache when appropriate.

When to use each method: repr() vs str()

  • Use __str__() for UI, CLI output, and messages shown to end users.
  • Use __repr__() for debugging, REPL development, and detailed logs.
  • In interactive shells the REPL displays __repr__() by design, which is why you often see constructor-like strings there.

Conclusion

Understanding python __str__ vs __repr__ is essential for clear python object string representation. Implement a helpful __repr__() for developers and add a concise __str__() for user-facing text. Follow best practices—make __repr__() as reconstructable as practical, avoid heavy work, and don’t eval untrusted output—to improve debugging, logging, and user experience.

Further reading

  • Python data model: special method names (official docs)
  • PEP and guides on string formatting and dataclasses

Stay updated with Netalith

Get coding resources, product updates, and special offers directly in your inbox.