Skip to content

str vs repr in Python: Explained

Updated on

In the realm of Python programming, __str__ and __repr__ are dunder (double underscore) methods, also known as magic methods or special methods. They serve as the backbone for object-oriented programming in Python. This comprehensive guide seeks to illuminate the distinctive functionalities of these two methods, their significance in Python, and the appropriate instances for their application. Additionally, this guide will present numerous code examples to cement the underlying concepts.

Want to quickly create Data Visualization from Python Pandas Dataframe with No code?

PyGWalker is a Python library for Exploratory Data Analysis with Visualization. PyGWalker (opens in a new tab) can simplify your Jupyter Notebook data analysis and data visualization workflow, by turning your pandas dataframe (and polars dataframe) into a tableau-alternative User Interface for visual exploration.

PyGWalker for Data visualization (opens in a new tab)

Defining the Terms: __str__ vs __repr__

Before diving into the deep end, let's start by defining these two important methods:

__str__ Method

In Python, __str__ is the method used to compute the "informal" or nicely printable string representation of an object. It is aimed at providing a human-readable output. Thus, readability is a key consideration when implementing this method.

Here's a simple example:

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.'
 
john = Person('John Doe', 30)
print(str(john))  # Outputs: John Doe is 30 years old.

__repr__ Method

On the other hand, __repr__ is a method used to compute the "official" string representation of an object. Its purpose is to provide a detailed representation that could be used to recreate the object if fed to the eval() function. It's particularly useful for debugging and logging, since it provides a comprehensive description of the object.

Consider the same Person class, but with a __repr__ method:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
    def __repr__(self):
        return f'Person(name={self.name}, age={self.age})'
 
john = Person('John Doe', 30)
print(repr(john))  # Outputs: Person(name=John Doe, age=30)

When to Use __str__ vs __repr__

Now that we have a basic understanding of these methods, let's explore when to use each one.

Implementing __str__ for User-friendly String Representation

The __str__ method is primarily aimed at end users. It provides an informal, more readable description of an object. You can think of it as a way of displaying objects in a way that makes sense to users who are not necessarily programmers.

When implementing this method in your Python classes, focus on delivering information that is most relevant and beneficial to the end-user.

class Product:
    def __init__(self, name, price):
        self.name = name
        self.price = price
 
    def __str__(self):
        return f'{self.name} costs ${self.price}.'
 
iPhone = Product('iPhone', 999)
print(str(iPhone))  # Outputs: iPhone costs $999.

In the above example, the __str__

method provides a simple, human-readable description of the Product object. The output from str(iPhone) could be displayed directly to users on a website or in an app.

Implementing __repr__ for Debugging and Development

The __repr__ method, conversely, is primarily intended for developers. It provides a complete and unambiguous representation of the object, which can be very useful for debugging and logging.

A golden rule when implementing the __repr__ method is that it should, if feasible, return a string that allows the recreation of the object using the eval() function. This isn't always achievable, especially for complex objects, but it's a good guideline to follow.

Consider the Product class with a __repr__ method:

class Product:
    def __init__(self, name, price):
        self.name = name
        self.price = price
 
    def __repr__(self):
        return f'Product(name={self.name}, price={self.price})'
 
iPhone = Product('iPhone', 999)
print(repr(iPhone))  # Outputs: Product(name=iPhone, price=999)

The __repr__ method's output is much more detailed and technical compared to the __str__ method. This level of detail is exactly what a developer needs for effective debugging or logging.

Tailoring __str__ and __repr__ for Your Python Classes

Now that you understand the primary use-cases for both methods, let's discuss how to tailor them to your needs. In many cases, you'll want to define both methods in your classes, but their implementation will depend heavily on your specific use-case.

Establishing __str__ for Custom Informal String Representation

When defining the __str__ method, think about the people who will be interacting with your object and what they need to know. The method should return a string that gives a concise, human-readable summary of the object.

Suppose we have a Movie class in a cinema ticket booking application:

class Movie:
    def __init__(self, title, director, rating):
        self.title = title
        self.director = director
        self.rating = rating
 
    def __str__(self):
        return f'{self.title} by {self.director}, rated {self.rating}/10.'
 
inception = Movie('Inception', 'Christopher Nolan', 8.8)
print(str(inception))  # Outputs: Inception by Christopher Nolan, rated 8.8/10.

Crafting __repr__ for Detailed Object Description

When implementing the __repr__ method, consider what would be useful for someone debugging the code or logging the state of an object. The string should include all of the information necessary to understand the object at a glance.

Continuing with the Movie class, a __repr__ method could look like this:

class Movie:
    def __init__(self, title, director, rating):
        self.title = title
        self.director = director
        self.rating = rating
 
    def __repr__(self):
        return f'Movie(title={self.title}, director={self.director}, rating={self.rating})'
 
inception = Movie('Inception', 'Christopher Nolan', 8.8)
print(repr(inception))  # Outputs: Movie(title=Inception, director=Christopher Nolan, rating=8.8)

FAQs: Understanding Python's __str__ and __repr__

We've now explored the core concepts of Python's __str__ and __repr__ methods. However, you may still have questions about these dunder methods. Let's address some frequently asked questions.

  1. What happens if I don't define __str__ and __repr__ in my Python class?

    If you don't define __str__ or __repr__ in your class, Python uses its default implementations. The default __str__ method returns a string containing the class name and its address in memory, while the default __repr__ does the same.

  2. Should I always implement both __str__ and __repr__ methods in my classes?

    It's good practice to implement at least __repr__, as it's used as a fallback if __str__ isn't defined. However, whether you implement both depends on your specific needs. If your class objects need to have a user-friendly string representation, then it's worth implementing __str__ as well.

  3. Can __str__ and __repr__ return any type of string?

    While __str__ and __repr__ can technically return any string, it's best to follow the conventions: __str__ should be readable and concise, while __repr__ should be detailed and, if possible, allow the object to be reproduced using eval().