Related Topics:
- String Concatenation and String Interpolation
- Python's Two Different String Representations
- String Representations for Classes
- What are Dunder Methods?
Transcript:
Let's talk about how to customize the string representations of your Python objects.
The default string representation
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>'
Explicit string conversions use __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)
Programmer-readable string conversions use __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 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.
You really only need __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)'
Summary
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.
from Planet Python
via read more
No comments:
Post a Comment