Python class __repr__ method converts string
Python class’s __repr__ method converts a string. After defining a custom class in Python, if you try to output its instance in the console or view it in the interpreter session, you won’t get very satisfactory results. The default “convert to string” functionality is very primitive and lacks detail:
class Car:
def __init__(self, color, mileage):
self.color = color
self.mileage = mileage
>>> my_car = Car('red', 37281)
>>> print(my_car)
<__console__.Car object at 0x109b73da0>
>>> my_car
<__console__.Car object at 0x109b73da0>
By default, you get a string containing the class name and the object instance id
(which is the memory address of the object in CPython). While better than nothing, it’s still pretty useless.
You might be able to work around this by printing the class attributes directly, or by adding a custom to_string()
method to the class:
>>> print(my_car.color, my_car.mileage)
red 37281
This general idea is correct, but it ignores Python’s conventions and built-in mechanisms for converting objects to strings.
So instead of building your own string conversion mechanism, add the double-underscore methods __str__
and __repr__
to your class. These two methods convert objects to strings in different situations in a Pythonic way.
Let’s see how these methods work in practice. First, add a __str__ method to the previous Car class:
class Car:
def __init__(self, color, mileage):
self.color = color
self.mileage = mileage
def __str__(self):
return f'a {self.color} car'
When you try to print or view a Car instance, you get a slightly improved result:
>>> my_car = Car('red', 37281)
>>> print(my_car)
'a red car'
>>> my_car
<__console__.Car object at 0x109ca24e0>
Viewing the Car
object in the console still returns the same result containing the object’s id
, but printing the object now returns the string returned by the newly added __str__
method.
__str__
is a double-underscore method in Python that is called when attempting to convert an object to a string:
>>> print(my_car)
a red car
>>> str(my_car)
'a red car'
>>> '{}'.format(my_car)
'a red car'
With a proper __str__
implementation, you can print objects without worrying about directly printing object attributes or writing a separate to_string()
function. This is Python’s signature string conversion method.
By the way, some people call Python’s double-underscore methods “magic methods.” There’s nothing magical about these methods; starting them with double underscores is just a naming convention that indicates they’re a core Python feature. Furthermore, adding double underscores helps avoid duplicating names with your own methods and attributes. Object constructors, such as __init__
, follow this convention; there’s nothing magical or mysterious about them.
So don’t be afraid to use Python’s double-underscore methods; they’re incredibly useful.
Python Class’s repr Method for String Conversion: __str__
vs. __repr__
Let’s continue with the string conversion problem. From the previous section, if you inspect my_car
in the interpreter session, you’ll still get the strange <Car object in 0x109ca24e0>
.
This happens because in Python 3, there are actually two double-underscore methods that can convert objects to strings. The first is __str__
, which we just introduced; the second is __repr__
, which works similarly to __str__
but is used in a different context.
Here’s a simple experiment to help you understand the use cases of __str__
and __repr__
. Let’s redefine the Car
class and add two double-underscore methods for converting to strings, producing different output:
class Car:
def __init__(self, color, mileage):
self.color = color
self.mileage = mileage
def __repr__(self):
return '__repr__ for Car'
def __str__(self):
return '__str__ for Car'
When you try the above example, you can see that each method generates the corresponding string conversion result:
>>> my_car = Car('red', 37281)
>>> print(my_car)
__str__ for Car
>>> '{}'.format(my_car)
'__str__ for Car'
>>> my_car
__repr__ for Car
Experimentally, when you inspect an object in a Python interpreter session, you get the object’s __repr__
result.
Interestingly, containers like lists and dictionaries always use the result of __repr__
to represent the contained object, even when calling str()
on the container itself:
str([my_car])
'[__repr__ for Car]'
Instead of manually selecting one string conversion method over another, such as to more clearly convey the intent of your code, it’s better to use the built-in str()
and repr()
functions. Using these two functions is preferable to calling an object’s __str__ or __repr__ directly because the results are the same but more aesthetically pleasing:
>>> str(my_car)
'__str__ for Car'
>>> repr(my_car)
'__repr__ for Car'
After introducing __str__ and __repr__, you might wonder how they differ in practice. Since these two functions seem to serve the same purpose, it might be confusing when to use them.
For this question, consider how the Python standard library handles it. Let’s create another experiment and see how it uses __repr__ and __str__ to control string conversion:
>>> import datetime
>>> today = datetime.date.today()
For date objects, the __str__ function returns a concise text representation that can be displayed to users with confidence. So, when you call str() on a date object, you get something that looks like an ISO date format:
>>> str(today)
'2017-02-02'
__repr__
focuses on obtaining an unambiguous result; the generated string is primarily intended to help developers debug their programs. To be as explicit as possible about what this object is, calling repr()
on it produces a more complex result, even including the full module and class name:
>>> repr(today)
'datetime.date(2017, 2, 2)'
Copying and pasting the string returned by this __repr__
statement recreates the original date
object as a valid Python statement. This is a nice practice and a good example to learn from when writing your own repr__
statements.
However, I find this pattern quite difficult to implement and is generally not worth the extra work. My rule of thumb is to make the string generated by __repr__
clear and helpful to the developer; it doesn’t need to be possible to recover the object’s full state.
Python Class repr Method Converts Strings to __repr__
If you don’t provide a __str__
method, Python will fall back to the result of __repr__
when looking for __str__
. Therefore, it’s recommended to always add a __repr__
method to your custom classes; it takes very little time but ensures usable string conversion results in almost all cases.
The following describes how to quickly and efficiently add basic string conversion functionality to your custom classes. For the previous Car
class, first add a __repr__
:
def __repr__(self):
return f'Car({self.color!r}, {self.mileage!r})'
Here, the
!r
conversion flag ensures that the output strings userepr(self.color)
andrepr(self.mileage)
instead ofstr(self.color)
andstr(self.mileage)
.
While this works correctly, it has the disadvantage of hard-coding the class name in the format string. A trick to avoid this hard-coding is to use the object’s__class__.__name__
attribute to get the class name as a string.
The advantage of this approach is that changing the class name doesn’t require modifying the implementation of__repr__
, thus better adhering to the “Don’t Repeat Yourself” (DRY) principle:
def __repr__(self):
return (f'{self.__class__.__name__}('
f'{self.color!r}, {self.mileage!r})')
The disadvantage is that the format string is very long and unwieldy. However, if carefully formatted, it can still maintain good code form and comply with PEP 8 standards.
With the above implementation of __repr__
, we get useful results when inspecting the object directly or calling repr()
:
>>> repr(my_car)
'Car(red, 37281)'
Printing the object or calling str()
will return the same string because the default implementation of __str__
simply calls __repr__
:
>>> print(my_car)
'Car(red, 37281)'
>>> str(my_car)
'Car(red, 37281)'
I think this is a standard approach that gets the job done with less effort and is straightforward to use in most cases. Therefore, I always add a basic __repr__
implementation to my custom classes.
Here is a complete example for Python 3, including an optional __str__
implementation:
class Car:
def __init__(self, color, mileage):
self.color = color
self.mileage = mileage
def __repr__(self):
return (f'{self.__class__.__name__}('
f'{self.color!r}, {self.mileage!r})')
def __str__(self):
return f'a {self.color} car'
Differences between Python class repr method for converting strings and __unicode__
In Python 3, the str
data type is used to represent text, which uses Unicode characters to represent most writing systems in the world.
Strings are represented using a different data model. There are two types for representing text: str
(limited to the ASCII character set) and unicode (equivalent to Python 3’s str
).
Due to this difference, Python 2 has an additional double-underlined method that controls string conversion: __unicode__
. In Python 2, __str__
returns bytes, while __unicode__
returns characters.
Using the new __unicode__
method to convert strings is preferred in most cases. There is also a built-in unicode()
function that calls the corresponding double-underlined method, similar to how str()
and repr()
work.
So far so good, but the rules for calling __str__ and __unicode__ in Python 2 are quite quirky: the print statement and str() call __str__; the built-in unicode() first calls __unicode__, and if __unicode__ isn’t available, it falls back to __str__, which decodes the result using the system text encoding.
Compared to Python 3, these special cases make the text conversion rules more complicated. However, they can be simplified for practical situations. Unicode is the preferred and trending approach for text processing in Python programs.
So, in general, it’s recommended to put all string formatting code in the __unicode__
method, then create a __str__
stub implementation that returns the Unicode representation encoded in UTF-8:
def __str__(self):
return unicode(self).encode('utf-8')
The __str__
stub function will be identical in most custom classes, so you can copy and paste it as needed (or place it in a base class). All string conversion code generated for non-developers should be in __unicode__
.
Here’s a complete example for Python 2.x:
class Car(object):
def __init__(self, color, mileage):
self.color = color
self.mileage = mileage
def __repr__(self):
return '{}({!r},
{!r})'.format( self.__class__.__name__,
self.color, self.mileage)
def __unicode__(self):
return u'a {self.color}
car'.format(self=self)
def __str__(self):
return unicode(self).encode('utf-8')
Key Points
-
Use the double-underscore methods
__str__
and__repr__
to take control of string conversion within your class. -
__str__
should produce readable results.__repr__
should produce unambiguous results. -
Always add
__repr__
to your class.__str__
calls__repr__
by default. -
Use
__unicode__
instead of__str__
in Python 2.