Let's talk about how to customize the string representations of your Python objects.
We have a Point
class here:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
We've made a new instance of this class and we're referring to that instance with the variable p
.
If we type p
from the Python REPL, we see that it's a point.Point
object at some memory location:
>>> p = Point(1, 2)
>>> p
<point.Point object at 0x7f128f519ee0>
If we print it we see the same thing:
>>> print(p)
<point.Point object at 0x7f128f519ee0>
And if we convert to a string explicitly, we see the same thing:
>>> str(p)
'<point.Point object at 0x7f128f519ee0>'
__str__
It would be nice to see something, besides the module name and the class name of this object.
Maybe the data that's actually stored in this object.
Let's create a __str__
method on this Point
class (pronounced "dunder str
", dunder meaning "double underscore"):
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f"({self.x}, {self.y})"
This will customize what happens when we pass the Point
object to the built-in str
function:
>>> p = Point(1, 2)
>>> str(p)
'(1, 2)'
>>> p.__str__()
'(1, 2)'
The built-in str
function actually calls the __str__
method on the object that we give it.
In fact, if we print something out or otherwise, implicitly convert something to a string, it does the same thing: it calls that __str__
method.
>>> print(p)
(1, 2)
__repr__
We're not done yet! Our Python object does not yet have a nice string representation in all cases.
If we type p
from the Python REPL, we still see the point.Point
object at some memory location:
>>> p
<point.Point object at 0x7f7e54f46be0>
The REPL actually doesn't use, the str
built-in function, it uses the built-in repr
function.
>>> repr(p)
'<point.Point object at 0x7f7e54f46be0>'
And the built-in repr
function relies on the __repr__
method:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Point({self.x}, {self.y})"
def __str__(self):
return f"({self.x}, {self.y})"
By making a __repr__
method, we've customized what happens when you call repr
on our Point
objects:
>>> p = Point(1, 2)
>>> repr(p)
'Point(1, 2)'
And by making a __str__
method, we've customized what happens when you call str
:
>>> str(p)
'(1, 2)'
And so when we just type p
or when we print(p)
, we'll get friendly string representations:
>>> p
Point(1, 2)
>>> print(p)
(1, 2)
So, we've customized the programmer-readable string representation for the object (which by convention looks like Python code) and a human-readable string representation for our object, which is what an end-user might expect to see.
__repr__
Almost every Python object only customizes one of these: __repr__
, the programmer readable string representation.
If we just define a __repr__
method on our class:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Point({self.x}, {self.y})"
It will customize what programmers see:
>>> p = Point(1, 2)
>>> p
Point(1, 2)
But it also customizes what happens when we print out our object:
>>> print(p)
Point(1, 2)
On when we convert it to a string explicitly:
>>> str(p)
'Point(1, 2)'
This happens because the default __str__
method on all Python objects delegates to the __repr__
method.
>>> p.__str__()
'Point(1, 2)'
When you're defining your own classes in Python, always make a __repr__
method.
If you want an additional human-readable string representation, you might wanna customize the __str__
method, but you *at least& need to customize the __repr__
method of your Python objects.
Hello friendly web visitor! 👋
This page is part of Python Morsels, an online Python skill-building service.
The best way to learn is by doing. In the case of Python that means writing Python code. If you'd like to improve your Python skills every week, try out Python Morsels by entering your email below to create an account.
Python Morsels topics pages are free and the first month's worth of exercises is free as well. You don't need to enter payment details to sign up.
You can find explanations of many other Python topics by signing up below.
By signing up, you agree to the Privacy Policy.
Need to fill-in gaps in your Python skills? I send regular emails designed to do just that.