Matus's Blog     

How come my class is not pretty-printed?

Do you ever wonder why some classes are pretty printed while others are not? Why Counter or dict prints its elements and your class outputs some gibberish?

Most of you have used Python dictionaries and it seems somehow natural, that it displays its elements when passed to print function. But what is displayed when we print a class we defined? Let’s try it with a simple class Point that will store coordinates x and y.

>>> class Point:
...     def __init__(self, x, y):
...         self.x = x
...         self.y = y
...
>>> a = Point(42, 47)
>>> print(a)
<__main__.Point object at ...>

It printed a position of an object in a memory. However, this behavior can be changed.

We can tell Python how to represent the object by using one of Python’s data model methods (also called magic methods). Data model methods is a special set of methods that Python uses/calls under the hood when some events occur. They are typically surrounded by double underscores. Actually, we have just used one (__init__) when creating a class. This one is called when you create a new instance of a class. The one that is called by print function is __str__.

Let’s implement it and print the instance one more time.

>>> class Point:
...     def __init__(self, x, y):
...         self.x = x
...         self.y = y
...
...     def __str__(self):
...         return 'x = {}, y = {}'.format(self.x, self.y)
...
>>> a = Point(42, 47)
>>> print(a)
x = 42, y = 47

That’s it, __str__ returns a string that is passed to print function.

Hey, I typed it in a Python console and it does not work

Sure, if you do not pass it to print function like this:

>>> class Point:
...     def __init__(self, x, y):
...         self.x = x
...         self.y = y
...
...     def __str__(self):
...         return 'x = {}, y = {}'.format(self.x, self.y)
...
>>> a = Point(42, -42)
>>> a
<__main__.Point object at ...>

Only a print and str functions invoke __str__ method. But what is called in case we just type it in a Python console? In those cases, Python invokes __repr__ method. It’s similar to __str__ and invoked every time except for those two.

What is the difference then? Why not have only one?

Basically, __str__ is for you to make the object more readable. __repr__ should look like a valid Python expression that could be used to recreate an object with the same value. To test it, you can pass your object to a repr function that will invoke the __repr__ method and then pass it to eval function. When implemented correctly, it will return a new instance of your class.

To visualize it, this is how it would look like in our Point class.

>>> class Point:
...    def __init__(self, x, y):
...        self.x = x
...        self.y = y
...
...    def __repr__(self):
...        return 'Point({}, {})'.format(self.x, self.y)
...
>>> a = Point(42, 47)
>>> b = eval(repr(a))
>>> b
Point(42, 47)
>>> b.x
42

Conclusion

By default, when passing an instance of a user-defined class to a print function, position of the instance in memory is displayed. Nonetheless, Python offers a way to change it. We can use of data model methods called __str__. It should return a string and it is invoked everytime your class is passed to print or str function. The second data model method that we used is __repr__, that should return a string that we can subsequently use to recreate the instance.