Use a Dunder Class Reference
00:00
I’ve just coded up .__str__()
and I’ve used the .animal_type
, which is a class attribute in my classes, but I’m accessing it through the instance.
00:09 So I want to show you what kind of troubles you can run into when you do that and also a solution for it.
00:16
Restart, and I will create the Dog
, d
again. Okay, of course now we’re running into an error because I added trait
as a required parameter. So now it’s not just "brown"
and called "Puppy"
, but it’s also not lazy at all.
00:35 It’s—what’s the opposite of lazy?—industrious.
00:42
Okay, so we have d.trait
. We have our industrious brown dog Puppy, and if I print()
the Dog
now, the Dog
instance, I should get back the string, and it says "The industrious brown dog Puppy
jumps over the lazy dog."
That’s the output that I was hoping for.
01:02
But now I want to redo the little problem that I did earlier. If I assign a new instance attribute on this Dog
object that shadows, the class attribute .animal_type
, then Python’s going to pick up that one first, and it’s not going to go back to the class attribute .animal_type
.
01:20
So let’s say d.animal_type = "fox"
and then print()
the Dog
object again.
01:28
Then you see that it says "The industrious brown fox Puppy jumps over the lazy
dog"
, which is closer to the original sentence, but it’s not what we want.
01:36 I want to make sure that in this output, I always still know that the instance is actually a dog and not a fox, even if I would accidentally add this instance attribute that shadows the class attribute.
01:50
But I don’t want to go into each of those child classes and implement a new .__str__()
method, where I then put in the .animal_type
directly from the class.
02:04
So instead of self.animal_type
or Animal.animal_type
, I’m going to say self.__class__.animal_type
, and this self.__class__
is going to always refer to the class that this instance was modeled from. In the Dog
class, this is going to be Dog
, and in the Pig
class it’s going to be Pig
, et cetera, so that the .animal_type
is actually going to be the class attribute, even if you accidentally override it and put an instance attribute of the same name in there. Long story short, let’s try it out.
02:43
Again, we need our "Puppy"
.
02:49
Try it out first. print(d)
still working. "The industrious brown dog
Puppy jumps over the lazy dog."
Great. And then if I create this instance attribute, .animal_type
, that shadows the class attribute, now if I print(d)
,
03:04
you can see that it still prints out dog
. It doesn’t take the instance attribute .animal_type
, but it still refers back to the class attribute.
03:13
So, a little hoop that I jumped through here just to make sure that I can also print()
out what type of animal an animal is and to keep this class attribute around without having to do a lot of code duplication.
03:27
There might be other ways to solve this, but I think this works well, and it was a nice chance to talk about some potential issues with class attributes. All right, Sheep
, Dog
, and Pig
can all have .name
, .color
, and .trait
and can print()
out nicely. Next, we also need some methods.
Become a Member to join the conversation.