Purpose of __str__ and __repr__ in Python
Before we dive into the discussion, let's check out the official documentation of Python about these two functions:
object.__repr__(self)
: called by therepr()
built-in function and by string conversions (reverse quotes) to compute the "official" string representation of an object.
object.__str__(self)
: called by thestr()
build-in function and by the print statement to compute the "informal" string representation of an object.Quote from Python's Data Model
From the official documentation, we know that both __repr__
and __str__
are used to "represent" an object. __repr__
should be the "official" representation while __str__
is the "informal" representation.
So, what does Python's default __repr__
and __str__
implementation of any object look like?
For example, let's say we have a int
x
and a str
y
and we want to know the return value of __repr__
and __str__
of these two objects:
[python]
>>> x = 1
>>> repr(x)
'1'
>>> str(x)
'1'
>>> y = 'a string'
>>> repr(y)
"'a string'"
>>> str(y)
'a string'
[/python]
While the return of repr()
and str()
are identical for int x
, you should notice the difference between the return values for str y
. It is important to realize the default implementation of __repr__
for a str
object can be called as an argument to eval
and the return value would be a valid str
object:
[python]
>>> repr(y)
"'a string'"
>>> y2 = eval(repr(y))
>>> y == y2
True
[/python]
While the return value of __str__
is not even a valid statement that can be executed by eval:
[python]
>>> str(y)
'a string'
>>> eval(str(y))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1
a string
^
SyntaxError: unexpected EOF while parsing
[/python]
Therefore, a "formal" representation of an object should be callable by eval() and return the same object, if possible. If not possible, such as in the case where the object's members are referring itself that leads to infinite circular reference, then __repr__
should be unambiguous and contain as much information as possible.
[python]
>>> class ClassA(object):
... def __init__(self, b=None):
... self.b = b
...
... def __repr__(self):
... return '%s(%r)' % (self.__class__, self.b)
...
>>>
>>> class ClassB(object):
... def __init__(self, a=None):
... self.a = a
...
... def __repr__(self):
... return "%s(%r)" % (self.__class__, self.a)
...
>>> a = ClassA()
>>> b = ClassB(a=a)
>>> a.b = b
>>> repr(b)
RuntimeError: maximum recursion depth exceeded while calling a Python object
[/python]
Instead of literally following the requirement of __repr__
for ClassB
which causes an infinite recursion problem where a.__repr__
calls b.__repr__
which calls a.__repr__
which calls b.__repr__,
on and on forever, you could define ClassB.__repr__
in a different way. A way that shows as much information about an object as possible would be just as good as a valid eval-confined __repr__
.
[python]
>>> class ClassB(object):
... def __init__(self, a=None):
... self.a = a
...
... def __repr__(self):
... return '%s(a=a)' % (self.__class__)
...
>>> a = ClassA()
>>> b = ClassB(a=a)
>>> a.b = b
>>> repr(a)
"<class '__main__.ClassA'>(<class '__main__.ClassB'>(a=a))"
>>> repr(b)
"<class '__main__.ClassB'>(a=a)"
[/python]
Since __repr__
is the official representation for an object, you always want to call "repr(an_object)"
to get the most comprehensive information about an object. However, sometimes __str__
is useful as well. Because __repr__
could be too complicated to inspect if the object in question is complex (imagine an object with a dozen attributes), __str__
is helpful to serve as a quick overview of complicated objects. For example, suppose you want to inspect a datetime
object in the middle of a lengthy log file to find out why the datetime
of a user's photo is not correct:
[python]
>>> from datetime import datetime
>>> now = datetime.now()
>>> repr(now)
'datetime.datetime(2013, 2, 5, 4, 43, 11, 673075)'
>>> str(now)
'2013-02-05 04:43:11.673075'
[/python]
The __str__
representation of now looks cleaner and easier to read than the formal representation generated from __repr__
. Sometimes, being able to quickly grasp what's stored in an object is valuable to grab the "big" picture of a complex program.
Gotchas between __str__ and __repr__ in Python
One important catch to keep in mind is that container's __str__
uses contained objects' __repr__
.
[python]
>>> from datetime import datetime
>>> from decimal import Decimal
>>> print((Decimal('42'), datetime.now()))
(Decimal('42'), datetime.datetime(2013, 2, 5, 4, 53, 32, 646185))
>>> str((Decimal('42'), datetime.now()))
"(Decimal('42'), datetime.datetime(2013, 2, 5, 4, 57, 2, 459596))"
[/python]
Since Python favours unambiguity over readability, the __str__
call of a tuple calls the contained objects' __repr__
, the "formal" representation of an object. Although the formal representation is harder to read than an informal one, it is unambiguous and more robust against bugs.
Tips and Suggestions between __str__ and __repr__ in Python
- Implement
__repr__
for every class you implement. There should be no excuse. - Implement
__str__
for classes which you think readability is more important of non-ambiguity.