A Complete Example & Best Practices
Learn why you should at least have a .__repr__()
method in your classes. This lesson will show you how to adhere to the Don’t Repeat Yourself (DRY) principle when working with .__repr__()
by taking advantage of __class__.__name__
:
class Car:
def __init__(self, color, mileage):
self.color = color
self.mileage = mileage
def __repr__(self):
return '{self.__class__.__name__}({self.color}, {self.mileage})'.format(self=self)
00:00
So, the next example I want to show you is an actual implementation that someone might take for their class. And because Python falls back to calling .__repr__()
if you don’t define a separate .__str__()
implementation, my recommendation is actually to put a .__repr__()
on any class that you define, because then you get a pretty helpful and readable result in all cases, and now what I’m going to do is also give you a complete example of how you would do that, because there’s a slight trick you can apply to make this a little bit easier to work with. So again, I’ve got my Car
class here, and I’m defining the .__repr__()
right now, and so how I would go about doing this is, well, returning a string that contains the Car
class name, and then I would probably do this self.color
,
00:52
and self.mileage
, right? And then, that’s a format string, and then I would just pass the self
object. Now, a common thing that I see here is that usually, you have to re-type the name of the class inside the .__repr__()
, but there’s actually a way to get around that—because we can just reach into the class itself and ask it for its name.
01:16
So, what you can do here instead is you can use self.__class__.__name__
. This is getting kind of long, so you want to make sure you format that in a way that’s sensible.
01:31 But basically, what this is going to do is it’s going to automatically use the right name for the class, so you don’t have to make sure you update this, right?
01:41
So, you might not want that in some cases—maybe you want the .__repr__()
class name to be static—but usually, this is a good default implementation for your .__repr__()
.
01:51
And now, when I create a new my_car
object and I inspect it, I get a really nice result.
01:59
And also, when I call str()
on it or when I print the Car
,
02:04
I get the same result, because the default implementation for str()
just calls .__repr__()
internally. Okay, so this is kind of the minimum implementation I would recommend to you, where you’re adding a .__repr__()
to any class that you define.
02:17
You kind of leave the .__str__()
on the side and you would use something like this so you don’t have to type the class name again.
justpeter25x on Nov. 16, 2019
can you please explain on this more:{self.class.name} For what you do that?
justpeter25x on Nov. 16, 2019
can you please explain here in this statement: return ‘{self.class.name}({self.color}, {self.mileage})’.format(self=self)
How i can return the statement in this way: return (‘{self.class.name} , {}, {} car’.format(self.color,self.mileage)) Is it possible?I try but i got the key error ‘self’
Learn2Improve on Dec. 4, 2019
@Pygator - if you are refering to difference between this and previous lesson - it is mentioned that it is best practice to at least have __repr__
method. If you don’t have a __str__
method and still call it - it will fallback to __repr__
method, so you have covered both cases (str(object)
and repr(object)
) via just __repr__
method.
If you do need to have __str__
method on top of __repr__
e.g. for more user friendly output - that is still possible and entirely dependent on your choice.
In code above if you add following at the end of the script (not indented):
car1 = Car("Red", 10000)
print(repr(car1))
print(str(car1))
When you execute the code you get following result:
Car(Red, 10000)
Car(Red, 10000)
As you can see both methods return same result because __str__
is not defined, hence it falls back to __repr__
method. If you do define __str__
method you would get different result. Here is example of adding __str__
to code from Dan (I have made changes by using f-string
instead of .format
):
class Car:
def __init__(self, color, mileage):
self.color = color
self.mileage = mileage
def __repr__(self):
return f'{self.__class__.__name__}({self.color}, {self.mileage})'
def __str__(self):
return f'My car color is: {self.color} and its mileage is: {self.mileage}!'
car1 = Car("Red", 10000)
print(repr(car1))
print(str(car1))
And result when you run this script is:
Car(Red, 10000)
My car color is: Red and its mileage is: 10000!
So, since both were defined, __str__
and __repr__
methods were called. And while first result gives exact code that was needed to create object (which would be useful for developer), second result (__str__
method) returns something that would be more understandable to end user who doesn’t really care what code is needed to create an object.
Hope it helps
L2I
Learn2Improve on Dec. 5, 2019
@justpeter25x
Regarding your question: can you please explain here in this statement:
return '{self.__class__.__name__}({self.color}, {self.mileage})'.format(self=self)
Please note that in Dan’s code under .format()
self
is defined (self=self
). This is because previous self occurences in {} inside quoatation marks are not automatically recognized as self
object, they are only defined within .format(self=self)
part of statement.
This is how string mehtod .format()
works. You cannot put variables directly in curly brackets with this method.
So, your code: return ‘{self.__class__.__name__} , {}, {} car’.format(self.color,self.mileage)
when it is read by Python does not know what self
in {self.__class__.__name__}
is, and returns KeyError
.
You do have alternative for your code to work by using f-strings (Python 3.6 and later). Since f-string allows you to call variables directly in {}, your statement would work if written like this: return f'{self.__class__.__name__}, {self.color}, {self.mileage} car'
For example, in this case if you run this script and then in console put:
car1 = Car("Red", 10000)
print(repr(car1))
Your result would be:
Car, Red, 10000 car
I am not sure if this is what you wanted to be shown, but you can work on your code from there.
Take care,
L2I
agerbes on Jan. 19, 2020
I tried to run the example. I wrote the class in a python script and ran it on the console. Unfortunately for me it doesn’t work as shown in the video. Just the print statement gives me an output, but not my_car or str(my_car).
Dan Bader RP Team on Jan. 20, 2020
@agerbes: If you can post a code example that’ll make it easier to figure out what’s happening. You can post it here or on Slack (#coding-questions
) so we can look into it :)
Become a Member to join the conversation.
Pygator on Aug. 29, 2019
This is great python knowledge. But what’s the point of the previous distinction? This is both human readable and unambigous.