Question

__str__ vs __repr__ in Python: What’s the Difference?

pythonmagic-methodsrepr

Question

In Python, what is the difference between __str__ and __repr__? When is each method used, and how should they be implemented in a class?

Short Answer

By the end of this page, you will understand what __str__ and __repr__ do in Python, how they differ, when Python calls each one, and how to write both methods clearly in your own classes.

Concept

In Python, __str__ and __repr__ are special methods used to create string representations of objects.

  • __str__ is meant for human-readable output.
  • __repr__ is meant for developer-focused output.

When you print an object, Python usually uses __str__ if it exists. When you inspect an object in the interpreter, debug it, or view it inside a container like a list, Python usually uses __repr__.

Why this matters

A good string representation helps in two important ways:

  • It makes program output easier for users to read.
  • It makes debugging easier for developers.

For example, if you create a Book object, a user might want to see:

The Hobbit by J.R.R. Tolkien

But a developer might want to see something more precise, such as:

Book(title='The Hobbit', author='J.R.R.R. Tolkien')

That second version is more useful when debugging because it shows the class name and field values.

The general rule

  • Use __str__ for a friendly description.
  • Use __repr__ for an unambiguous representation.

A common Python guideline is:

__repr__ should, if possible, return a string that could be used to recreate the object.

That is not always possible, but it is a good goal.

Fallback behavior

If a class does not define __str__, Python falls back to __repr__.

If neither is defined, Python uses the default object representation, which looks something like this:

<__main__.Book object at 0x1048c7d90>

That default is valid, but usually not very helpful.

Mental Model

Think of an object as a product in a store.

  • __str__ is the label shown to customers.
  • __repr__ is the internal inventory record used by staff.

A customer-facing label should be simple and readable. An inventory record should be precise and useful for tracking exactly what the item is.

For a User object:

  • __str__ might be: Alice
  • __repr__ might be: User(name='Alice', id=42)

Both describe the same object, but for different audiences.

Take Quiz

Syntax and Examples

The basic syntax looks like this:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return f"{self.name} is {self.age} years old"

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

Example usage

person = Person("Maya", 30)

print(person)        # uses __str__
person               # interpreter often shows __repr__
repr(person)         # directly uses __repr__
str(person)          # directly uses __str__

Expected output:

Maya is 30 years old

And repr(person) would return:

"Person(name='Maya', age=30)"

Why use !r in f-strings?

In this line:

return f"Person(name={self.name!r}, age={self.age!r})"

!r tells Python to use the repr() form of each value. This is helpful because strings will include quotes, making the output clearer and less ambiguous.

For example:

name = "Maya"
print(f"{name}")    # Maya
print(f"{name!r}")  # 'Maya'

Step by Step Execution

Consider this code:

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

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

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

item = Product("Pen", 2.5)
print(item)
print(repr(item))
print([item])

What happens step by step

  1. Python creates a Product object with:

    • name = "Pen"
    • price = 2.5
  2. print(item) is called.

    • print() tries to get a human-friendly string.
    • Python calls item.__str__().
    • The result is:
    "Pen costs $2.5"
    
  3. print(repr(item)) is called.

    • repr(item) explicitly calls item.__repr__().
    • The result is:
    "Product(name='Pen', price=2.5)"
    
  4. print([item]) is called.

    • Python prints a list.
    • For objects inside containers like lists, Python uses __repr__ for each element.
    • The result is something like:
    [Product(name='Pen', price=2.5)]
    

This is one reason __repr__ is especially useful for debugging.

Real World Use Cases

Here are common places where these methods matter:

User-facing output

If your program shows objects to users, __str__ can make the output clean.

Examples:

  • CLI tools displaying records
  • Logging readable status messages
  • Printing summaries in scripts

Debugging and development

__repr__ helps developers understand what an object contains.

Examples:

  • Inspecting objects in a debugger
  • Seeing values in logs
  • Printing lists of custom objects
  • Debugging API response wrappers

Data models

In apps that use classes for business data, both methods are useful.

Examples:

  • User, Order, Product, Invoice
  • File or configuration objects
  • Database row wrappers

Libraries and frameworks

Library authors often implement __repr__ so developers can inspect objects easily. A good __repr__ saves time when reading logs or debugging state.

Take Quiz

Real Codebase Usage

In real projects, developers usually follow a few patterns.

Pattern: always implement __repr__

If you implement only one of the two, __repr__ is usually the more important choice because it helps with debugging.

class Config:
    def __init__(self, env, debug):
        self.env = env
        self.debug = debug

    def __repr__(self):
        return f"Config(env={self.env!r}, debug={self.debug!r})"

Pattern: __str__ for friendly summaries

If an object is often shown to users, add __str__ too.

class Config:
    def __init__(self, env, debug):
        self.env = env
        self.debug = debug

    def __repr__(self):
        return f"Config(env={self.env!r}, debug={self.debug!r})"

    def __str__(self):
        return f"Environment: {self.env}, Debug: {self.debug}"

Pattern: include key fields, not everything

In large classes, developers often include only the most useful fields in __repr__. This keeps logs readable.

Pattern: avoid expensive work

These methods should usually be quick and safe. Do not put slow database calls, file reads, or network requests inside them.

Pattern: avoid sensitive data

Do not expose passwords, tokens, or private keys in __repr__ or __str__.

Bad example:

class Credentials:
    def __repr__(self):
        return "Credentials(username='admin', password='secret')"

Safer version:

class Credentials:
    def __init__(self, username, password):
        self.username = username
        self.password = password

    def __repr__(self):
        return f"Credentials(username={self.username!r}, password='***')"

Common Mistakes

1. Returning something that is not a string

Both methods must return a string.

Broken code:

class Item:
    def __repr__(self):
        return 123

This causes a TypeError.

Correct version:

class Item:
    def __repr__(self):
        return "Item()"

2. Making __str__ and __repr__ identical without thought

This is not always wrong, but they serve different purposes. If you make them the same, do it intentionally.

3. Writing vague __repr__ output

Bad:

def __repr__(self):
    return "object data"

This gives very little debugging value.

Better:

def __repr__(self):
    return f"Order(id={self.id!r}, total={self.total!r})"

4. Forgetting that containers use __repr__

Beginners often expect lists to show __str__ output.

class Animal:
    def __str__(self):
        return "Cat"

pet = Animal()
print(pet)     # Cat
print([pet])   # uses __repr__, not __str__

If __repr__ is missing, Python may show the default memory-address style output inside the list.

5. Exposing sensitive information

Never include secrets in these methods. Logs and debugging output may be stored or shared.

6. Doing too much work inside the method

These methods should describe the object, not perform heavy logic. Keep them simple.

Comparisons

ConceptPurposeTypical AudienceCommon Usage
__str__Readable descriptionEnd usersprint(obj), str(obj)
__repr__Precise/debug representationDevelopersrepr(obj), interpreter, containers

str(obj) vs repr(obj)

class User:
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return self.name

    def __repr__(self):
        return f"User(name={self.name!r})"
user = User("Ava")
print(str(user))   # Ava
print(repr(user))  # User(name='Ava')

What if only __repr__ exists?

Python will use it as a fallback for str().

class User:
    def __repr__(self):
        return "User('Ava')"

user = User()
print(user)  # User('Ava')

What if only __str__ exists?

print(obj) may look fine, but debugging and list output may still be poor because __repr__ is missing.

Take Quiz

Cheat Sheet

class MyClass:
    def __str__(self):
        return "human-readable text"

    def __repr__(self):
        return "DeveloperFocused(value='example')"

Quick rules

  • __str__ = friendly output
  • __repr__ = precise/debug output
  • print(obj) usually uses __str__
  • repr(obj) uses __repr__
  • Interpreter display usually uses __repr__
  • Lists, dicts, and other containers usually use contained objects' __repr__
  • If __str__ is missing, Python falls back to __repr__
  • Both methods must return strings

Good __repr__ guidelines

  • Include class name
  • Include important fields
  • Use !r in f-strings when helpful
  • Keep it unambiguous
  • Avoid secrets
  • Avoid expensive computation

Common pattern

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

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

    def __str__(self):
        return f"{self.name}, age {self.age}"

FAQ

Should I always implement both __str__ and __repr__?

Not always. If you implement only one, __repr__ is usually the better choice because it helps with debugging.

Why does print(obj) show something different from typing obj in Python?

print(obj) usually uses __str__, while the interpreter display usually uses __repr__.

Can __repr__ and __str__ return the same value?

Yes. That is acceptable if one string works well for both users and developers.

What should __repr__ look like?

Ideally, it should be clear, specific, and, when practical, look like code that could recreate the object.

Why does a list show __repr__ instead of __str__?

Containers such as lists use the repr() of their elements so the output is more precise and useful for debugging.

What happens if I define neither method?

Python uses the default object representation, which includes the class name and memory address-like information.

Can these methods raise errors?

Yes, if they return a non-string value or contain broken logic. Keep them simple and safe.

Take Quiz

Mini Project

Description

Create a small Python class that models a book in a reading app. The project demonstrates how __str__ and __repr__ serve different purposes: one for friendly display and one for debugging.

Goal

Build a Book class that provides both user-friendly and developer-friendly string output.

Requirements

  • Create a Book class with title, author, and year attributes.
  • Implement __str__ to return a readable sentence for users.
  • Implement __repr__ to return a precise representation with the class name and field values.
  • Create at least two Book objects and print them individually.
  • Print a list of books to observe how __repr__ is used in containers.
Take Quiz

Keep learning

Related questions

View more