When Should You Use .__repr__() vs .__str__() in Python?

When Should You Use .__repr__() vs .__str__() in Python?

by Stephen Gruppetta intermediate best-practices

Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: When to Use .__repr__() vs .__str__() in Python

One of the most common tasks that a computer program performs is to display data. The program often displays this information to the program’s user. However, a program also needs to show information to the programmer developing and maintaining it. The information a programmer needs about an object differs from how the program should display the same object for the user, and that’s where .__repr__() vs .__str__() comes in.

A Python object has several special methods that provide specific behavior. There are two similar special methods that describe the object using a string representation. These methods are .__repr__() and .__str__(). The .__repr__() method returns a detailed description for a programmer who needs to maintain and debug the code. The .__str__() method returns a simpler description with information for the user of the program.

The .__repr__() and .__str__() methods are two of the special methods that you can define for any class. They allow you to control how a program displays an object in several common forms of output, such as what you get from the print() function, formatted strings, and interactive environments.

In this tutorial, you’ll learn how to differentiate .__repr__() vs .__str__() and how to use these special methods in the classes you define. Defining these methods effectively makes the classes that you write more readable and easier to debug and maintain. So, when should you choose Python’s .__repr__() vs .__str__?

In Short: Use .__repr__() for Programmers vs .__str__() for Users

Python classes have a number of special methods. These methods have a double leading underscore and a double trailing underscore in their names. You can informally refer to them as dunder methods because of the double underscores in their names.

The special methods .__repr__() and .__str__() both return string representations of the object. A string representation is a string that shows information about the object. You can tailor this information for different audiences, such as program users or your fellow programmers.

Like with other special methods with leading and trailing double underscores in their names, you can define these methods for any class.

The reason there are two methods to display an object is that they have different purposes:

  • .__repr__() provides the official string representation of an object, aimed at the programmer.
  • .__str__() provides the informal string representation of an object, aimed at the user.

The target audience for the string representation returned by .__repr__() is the programmer developing and maintaining the program. In general, it provides detailed and unambiguous information about the object. Another important property of the official string representation is that a programmer can normally use it to re-create an object equal to the original one.

The .__str__() method provides a string representation targeted to the program’s user, who may not necessarily be a Python programmer. Therefore, this representation enables any user to understand the data contained in the object. Usually, it’s simpler and easier to read for a user.

One way of displaying both representations of an object is by using Python’s standard REPL. The REPL will display the string representation from .__repr__() when you evaluate a line that only has an object on it. However, the built-in function print() shows the informal string representation returned by .__str__().

You can view the strings returned by .__repr__() vs .__str__() for an instance of the datetime class in the datetime module:

Python
>>> import datetime
>>> today = datetime.datetime.now()

>>> today
datetime.datetime(2023, 2, 18, 18, 40, 2, 160890)

>>> print(today)
2023-02-18 18:40:02.160890

You create a datetime.datetime object named today using .now(). This method returns the current date and time. When you evaluate the line containing only the variable name today, the REPL displays the string representation returned by .__repr__(). This representation shows the name of the data type and all the arguments needed to re-create the object.

When you use print(), the REPL displays the representation returned by .__str__(). This string shows the ISO standard format for displaying dates and times. Therefore, this is not a Python-specific format but a standard that’s used more broadly to represent dates and times.

Often, the official string representation is a valid Python expression that you can use to create a new object with the same value. You can confirm this with the datetime.datetime object by copying the official string representation and assigning it to a new name. You can also attempt to use the informal string representation, but this won’t work:

Python
>>> new_date = datetime.datetime(2023, 2, 18, 18, 40, 2, 160890)
>>> new_date == today
True

>>> new_date = 2023-02-18 18:40:02.160890
Traceback (most recent call last):
  ...
  File "<input>", line 1
    new_date = 2023-02-18 18:40:02.160890
                          ^
SyntaxError: leading zeros in decimal integer literals are not permitted ...

The output you got from .__repr__() when you evaluated today in the REPL created a new object equal to the original one.

However, the string representation from .__str__(), which you got when you used print(), isn’t a valid Python expression, so it raises a SyntaxError.

You can also show the string representations for common built-in data types:

Python
>>> 5
5
>>> print(5)
5

>>> greeting = "How are you?"
>>> greeting
'How are you?'
>>> print(greeting)
How are you?

Python’s REPL returns the official string representation defined by .__repr__() when you evaluate a line that includes only the object or its variable name. But what’s happening with print()? In the examples above, the official string representation is identical or nearly the same as the informal string representation, which print() returns. Both representations are based largely on the literals that you used to create the objects.

Other built-in data types also have the same official and informal string representations. In these cases, both representations are equal to the literal used for these objects.

You can view the representations for lists and dictionaries in the following example:

Python
>>> [10, 20, 30]
[10, 20, 30]
>>> print([10, 20, 30])
[10, 20, 30]

>>> {"name": "Homer", "role": "author"}
{'name': 'Homer', 'role': 'author'}
>>> print({"name": "Homer", "role": "author"})
{'name': 'Homer', 'role': 'author'}

These representations are unambiguous and can re-create an object with the same value. However, they’re also sufficiently clear for a program’s user because they convey the information contained in the object and can’t be simplified further. These objects don’t need different string representations for the programmer and user.

In this section, you’ve learned that the official string representation returned by .__repr__() contains unambiguous information about the object, aimed at the programmer. You can generally use this representation to create an object with the same values as the original one.

In contrast, the informal string representation returned by .__str__() is aimed at the user and is normally simpler. The literals used for most built-in data types are used as both the informal and official string representations for these types.

In the next section of this tutorial, you’ll learn about other ways to get the two string representations in Python.

How Can You Access an Object’s String Representations?

You’ve seen how you can display both string representations in the standard Python REPL. Up to this point, you’ve been using special methods to do this. But in general, you can also access the official and informal string representations using the built-in functions repr() and str().

When you pass an object as an argument to either repr() or str(), you’re calling the object’s .__repr__() or .__str__() method under the hood. You can confirm this using the datetime.datetime object you created in the previous section:

Python
>>> import datetime
>>> today = datetime.datetime.now()

>>> repr(today)
'datetime.datetime(2023, 2, 18, 18, 40, 2, 160890)'
>>> today.__repr__()
'datetime.datetime(2023, 2, 18, 18, 40, 2, 160890)'

>>> str(today)
'2023-02-18 18:40:02.160890'
>>> today.__str__()
'2023-02-18 18:40:02.160890'

When you pass today to the built-in function repr(), the program calls today.__repr__(). Although you can call the special method directly by calling today.__repr__(), it’s best to use the built-in function repr() since you shouldn’t access special methods directly whenever possible. The purpose of special methods is to provide additional functionality to an object rather than to be called directly.

You can use str() in a similar manner. It calls its argument’s .__str__() method.

You must pass the object as an argument to repr() and str(). However, .__repr__() and .__str__() are methods and don’t require any additional argument. As with all instance methods, the object itself is passed to the method as its first argument. In the case of .__repr__() and .__str__(), the object is also the only argument, as these methods don’t take any further arguments.

You can also display the string representations of an object using the built-in function format(), the string method .format(), or f-strings. You can start by passing the datetime object today to the function format() and the method .format():

Python
>>> format(today)
'2023-02-18 18:40:02.160890'

>>> "{}".format(today)
'2023-02-18 18:40:02.160890'

By default, these return the informal string representation of an object which is returned by .__str__(). You’ll see how to override the default representation when you explore f-strings in the rest of this section.

You’re most likely to use f-strings when formatting strings since they’re the newest form of string formatting in Python. You can display the object today using f-strings:

Python
>>> f"{today}"
'2023-02-18 18:40:02.160890'

As was the case with format() and .format(), f-strings display the informal string representation that .__str__() returns. You can get the official string representation from .__repr__() by using the string conversion flag "!r" in the f-string:

Python
>>> f"{today!r}"
'datetime.datetime(2023, 2, 18, 18, 40, 2, 160890)'

The conversion flag "!r" overrides the default for f-strings and calls the object’s .__repr__() method.

You can also use f-strings with an equal sign (=) to show both the variable name and its value. You’ll use this option primarily for debugging purposes:

Python
>>> f"{today = }"
'today = datetime.datetime(2023, 2, 18, 18, 40, 2, 160890)'

Note that when you use an equal sign, the f-string defaults to using the official string representation returned by .__repr__(). The representation aimed at the programmer is the most appropriate in this case since the equal sign in f-strings is normally used for debugging a program.

You can override this behavior using the conversion flag "!s":

Python
>>> f"{today = !s}"
'today = 2023-02-18 18:40:02.160890'

When you use the "!s" conversion, the f-string uses the informal string representation.

In the next section, you’ll learn how to add .__repr__() and .__str___() methods to the classes you define.

Should You Define .__repr__() and .__str__() in a Custom Class?

When you define a class, you can define several special methods to add functionality to the class. You can read more about defining classes in the tutorial Object-Oriented Programming (OOP) in Python.

You can explore string representation with user-defined classes by defining a class named Book. You can use a script named book.py to define this class:

Python
# book.py

class Book:
    def __init__(self, title, author):
        self.title = title
        self.author = author

odyssey = Book("The Odyssey", "Homer")

print(odyssey)

You define the class Book with an .__init__() method. There are two required arguments when initializing the class, title and author.

You create an instance of this class with the title and author of the book The Odyssey, and you pass odyssey to the print() function. You use print() because when you evaluate a line that only contains the variable name in a script, no output is printed. When you run this script, you get the following output:

Shell
$ python book.py
<__main__.Book object at 0x1025c4ed0>

This output is the default string representation of an object that’s inherited from the object class. The object class is the base class for all Python classes. It shows:

  • __main__.Book: The name of the class and where it’s defined
  • 0x1025c4ed0: The memory address of the object

This default representation tells you the name of the class and the memory address, which is shown as a hexadecimal value. In CPython, the memory address is the same as the object’s identity. You can find an object’s identity using the built-in function id(), which returns an integer rather than a hex value.

However, the memory address is rarely useful. This default representation doesn’t provide any additional information about the object that would be useful for the user or the programmer.

Both repr() and str() return this string representation by default:

Python
# book.py

class Book:
    def __init__(self, title, author):
        self.title = title
        self.author = author

odyssey = Book("The Odyssey", "Homer")

print(repr(odyssey))
print(str(odyssey))

You call repr(odyssey) and str(odyssey) and print out the values they return. The output shows the same default representation for both:

Shell
$ python book.py
<__main__.Book object at 0x100d046d0>
<__main__.Book object at 0x100d046d0>

This output confirms that only the default representation is available at the moment.

You can define the .__repr__() special method for this class:

Python
# book.py

class Book:
    def __init__(self, title, author):
        self.title = title
        self.author = author

    def __repr__(self):
        class_name = type(self).__name__
        return f"{class_name}(title={self.title!r}, author={self.author!r})"

odyssey = Book("The Odyssey", "Homer")

print(repr(odyssey))
print(str(odyssey))

The .__repr__() method has no additional parameters other than self and must always return a string. The output from this code shows that both repr(odyssey) and str(odyssey) return the string representation that you just defined:

Shell
$ python book.py
Book(title='The Odyssey', author='Homer')
Book(title='The Odyssey', author='Homer')

The repr() built-in function calls the object’s .__repr__() method. If a class doesn’t have a .__str__() method defined, then str() will also default to the object’s .__repr__() method.

You define the return value for .__repr__() to include the name of the class followed by parentheses (()) and the two arguments required to initialize the class. This format is ideal for the official string representation since it represents a valid Python expression that can re-create an object equal to the original one. Whenever possible, you should use this format for the official string representation.

Next, you can define the .__str__() method for the class:

Python
# book.py

class Book:
    def __init__(self, title, author):
        self.title = title
        self.author = author

    def __repr__(self):
        class_name = type(self).__name__
        return f"{class_name}(title={self.title!r}, author={self.author!r})"

    def __str__(self):
        return self.title

odyssey = Book("The Odyssey", "Homer")

print(repr(odyssey))
print(str(odyssey))

You define the .__str__() special method, which shouldn’t have any additional parameters other than self and should return a string. The string representation can be any string that you feel would be most beneficial for the program’s user. The output from this version of the code shows both the official and informal string representations, in that order:

Shell
$ python book.py
Book(title='The Odyssey', author='Homer')
The Odyssey

The informal string representation returned by .__str__() only shows the book’s title and doesn’t have a reference to the class name either. You can customize the informal string representation to suit your needs:

Python
# book.py

class Book:
    def __init__(self, title, author):
        self.title = title
        self.author = author

    def __repr__(self):
        class_name = type(self).__name__
        return f"{class_name}(title={self.title!r}, author={self.author!r})"

    def __str__(self):
        return f'"{self.title}" by {self.author}'

odyssey = Book("The Odyssey", "Homer")

print(repr(odyssey))
print(str(odyssey))

The string returned by .__str__() now has the book’s title in quotation marks followed by the author’s name. Note that if you want to use double quotation marks within a string, you can use single quotation marks to denote the string. The output from this code shows the official representation first, followed by the modified informal string representation:

Shell
$ python book.py
Book(title='The Odyssey', author='Homer')
"The Odyssey" by Homer

The official string representation includes all the details needed by a programmer, and it allows you to replicate the object to explore it further. This has a couple of major benefits:

  • It makes the program more maintainable.
  • It facilitates debugging.

You can use the expression in this string representation to create an object with the same values as the original one. This feature is useful during debugging as you or a fellow programmer replicates an object to explore it further.

However, the informal string representation has a friendlier format that’s better suited for a program’s user. This representation makes the output more readable for a user.

When you define a class, it’s a best practice to include the official string representation by defining .__repr__(). By including this method, you avoid the default representation, which isn’t very useful in most cases. This method will also provide a fallback option for the informal string representation, which comes in handy when you can use the same representation for both use cases.

If you need to display the object to a user, then you can also define .__str__(). This method will provide an output that’s easier for the user to understand.

If you’re using Python’s data classes, a default official string representation is already included. You don’t need to define .__repr__() yourself unless you want to override the default format.

You’re now ready to include string representations in any class that you define.

Conclusion

In this tutorial, you’ve learned the difference between official and informal string representations of Python objects. The special method .__repr__() returns the official string representation, which is aimed at programmers as they develop and maintain a program. The special method .__str__() returns the informal string representation, a friendlier format for the program’s user.

Now, you can distinguish between these two representations and know which one to expect in different situations. And if you haven’t been doing this already, you’ll never write another class without defining at least the .__repr__() method to provide the official string representation.

Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: When to Use .__repr__() vs .__str__() in Python

🐍 Python Tricks 💌

Get a short & sweet Python Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team.

Python Tricks Dictionary Merge

About Stephen Gruppetta

Stephen worked as a research physicist in the past, developing imaging systems to detect eye disease. He now focuses on Python education!

» More about Stephen

Each tutorial at Real Python is created by a team of developers so that it meets our high quality standards. The team members who worked on this tutorial are:

Master Real-World Python Skills With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

Master Real-World Python Skills
With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

What Do You Think?

Rate this article:

What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment below and let us know.

Commenting Tips: The most useful comments are those written with the goal of learning from or helping out other students. Get tips for asking good questions and get answers to common questions in our support portal.


Looking for a real-time conversation? Visit the Real Python Community Chat or join the next “Office Hours” Live Q&A Session. Happy Pythoning!