Detailing Official String Representation With .__repr__()
00:00
Now let’s get into developer-friendly string representations. The __repr__()
, or represent method in Python is used to define the official string representation of an object and show the way the object is constructed in code, mainly for developers and debugging purposes.
00:23
Let’s go back to the Storage
class and implement the __repr__()
method to return a developer-friendly string.
00:33
Since this is the official representation, let’s do return
f"
for format, and you need to include the name of the class, so Storage(
)
, you need the value so in curly brackets, .self.value
, comma, and you also need to include the units and you need to make sure that this will be a string.
01:01
So you can use quotations, curly bracket .self.unit
. Now to access the __repr__
string, let’s print(__repr__(
storage_size))
, and then let’s run the code.
Bartosz Zaczyński RP Team on Jan. 13, 2025
@Andras When you call super.__str__()
in your .__repr__()
method, you essentially bypass your custom .__str__()
method defined within the same class. Instead, the processing goes directly to the parent’s class implementation or object.__str__()
, which by default calls your .__repr__()
method again, causing a recursion error. One way to break that cycle is to call self.__str__()
instead of super().__str__()
or (better yet) str(self)
, like so:
class Storage(float):
def __new__(cls, value, unit):
instance = super().__new__(cls, value)
instance.unit = unit
return instance
def __str__(self):
return f"{super().__repr__()} {self.unit}"
def __repr__(self):
return f'Storage({str(self)}, "{self.unit}")'
What’s confusing about this is that both str()
and repr()
functions will call different special methods depending on which ones are available.
Become a Member to join the conversation.
Andras on Jan. 10, 2025
You don’t have to create the
instance.value
attribute becauseinstance
is already afloat
and represents the value. This is enough:In the REPL:
The only tricky bit with this code, which I don’t fully understand yet, is that you have to call
super().__repr__()
in both cases; this is the only way it works as expected. Naively, you would think that sincefloat.__str__()
andfloat.__repr__()
gives the same result, you could call either of these in either methods. But if you do, it will either produce'Storage(512.0, "GB") GB'
orRecursionError
. I would be very much interested what happens in these cases in detail…