Intermediate Python Inheritance
Transcript from the "Inheritance" Lesson
>> Nina Zakharenko: One more topic to cover before we go into our exercise is inheritance.
>> Nina Zakharenko: As you saw on this classes in Python help us make reusable code. And I'm gonna make a new file here, and I'm gonna save that, and I'm gonna call it vehicle
>> Nina Zakharenko: We'll call that py.
>> Nina Zakharenko: Okay.
>> Nina Zakharenko: Sometimes we want our classes to share properties between each other. So we saw that my car had four wheels. Well, I could also have a motorcycle, and my motorcycle will have two wheels but it still runs, right? So inheritance is a way the kind of make type that have should attribute.
[00:00:59] It helps us break an organizer code in a hierarchy from more generic to more specific. Objects that belong to classes higher up the hierarchy, the more generic ones, they're accessible via the more specific sub-classes, but not vice versa.
>> Nina Zakharenko: Earlier, we saw that,
>> Nina Zakharenko: The bull type issubclass,
>> Nina Zakharenko: Sorry, I forgot the arguments and instead of scrolling through my history, I'm just gonna show you the quickest way to get help on that. So the first thing is the cls, and the second thing is the class_or_tuple, so,
>> Nina Zakharenko: issubclass x, okay. So I would ask, issubclass of bool and int, both of the arguments have to be a class there.
[00:02:18] Okay, true. So just like we saw earlier this Boolean subclass it took all of the properties of int, and then it added to and extended them, right? So it's still got all the stuff that's under the hood. You can be weird and add them together, but it has a lot more properties.
[00:02:43] We can do the same thing with our classes as well. So looking at this vehicle.py file, I'm gonna make a class vehicle,
>> Nina Zakharenko: And I'm gonna make a __init__ for it. What does the first argument to __init__ have to be?
>> Speaker 2: Self.
>> Nina Zakharenko: And I'm gonna put a make here and a model And the type of fuel that it takes, just like in other types of functions I can pass in a default argument here.
[00:03:24] Just remember that all of those default arguments have to come last in order. How do I save these parameters that are passed into my instance?
>> Speaker 2: Self.make.
>> Nina Zakharenko: Right, so self.make is gonna be the passed in make. Self.model is gonna be the passed in model. And self.fuel is gonna be the passed in fuel.
[00:03:49] For you more advanced folks who wanna do more research after class. There's a great thing in Python 3.7 called a data class, that is kind of a special type of more advanced class that kind of helps you do a lot less of this kind of template stuff. Cuz the more arguments you add, if you want to save them into the instance, you're gonna have to kind of have a long list of assignments here
>> Nina Zakharenko: Okay, and then I'm gonna make a new class now for my Car, and it's going to inherit and extend from vehicle. And in order to do that, I add some parentheses here. And then I put in the class that I want to extend from. So notice this is the type, it's not an instance, right?
[00:04:40] This is the type I want to inherit from. And my car is going to have its own constructor.
>> Nina Zakharenko: And it's gonna take self again. It's gonna take the make, the model. It's gonna take the fuel. But it's also gonna take another optional argument, number_wheels.
>> Nina Zakharenko: If I want to call the constructor on my vehicle, because I already do, I wrote the code to do most of the stuff just adding on a little bit of extra.
[00:05:34] I have to use a special keyword in Python called super. And if you use Python 2 or if you've seen Python 2, this super keyword is just a bit of a mess. In Python 3, it's a lot easier, he just used the super keyword, you kinda call it with this empty,
>> Nina Zakharenko: Empty string and you do the method of the super class that you want to call, and then you pass in the arguments.
>> Nina Zakharenko: So this just calls, these were part of the parameters I gave, but we missed something. We're passing in a new parameter. What do we have with the number of wheels?
>> Speaker 2: Assign it to self.
>> Nina Zakharenko: Assign it to self, all right?
>> Nina Zakharenko: Okay, I'm gonna copy over this of reload stuff, this reload comment to the top here.
>> Nina Zakharenko: So it's a little more, we're not usually changing a file this much, and I'm gonna open my REPL again.
[00:06:55] So now I'm gonna say, import vehicle, and I'm gonna make a new car. I'm gonna say, my_subaru = actually, before I do that, I'm gonna make a new vehicle, right? This super class, maybe I have a four_by_four, right? It doesn't fit into the other categories. So I'm gonna say that my four_by_four is a vehicle.
[00:07:31] And the make of it, I don't know about four_by_four. So I'm gonna say, the make of it is zoom, and the model is it goes fast, and the fuel is cooking oil, it's very efficient. I'm sorry, I had to do a vehicle.vehicle
>> Nina Zakharenko: Usually it would just say from vehicle import, the vehicle class, but because I have to reload we're kind of doing it this way.
[00:08:02] Okay, so now my four_by_four,
>> Nina Zakharenko: It has a make, it has a model, and it has a fuel.
>> Nina Zakharenko: I'm gonna make a new instance of Car.
>> Nina Zakharenko: So I'm gonna say my_subaru is a vehicle.Cars, and the make is Subaru and the model is cross trek, and the fuel is diesel.
>> Nina Zakharenko: I'm sorry, I called it Car, so vehicle.Car, okay? So I have my_subaru instance now. My_subaru.make, my_subaru.model, my_subaru.fuel. Does my_subaru.num_wheels variable? Does it?
>> Speaker 2: [INAUDIBLE]
>> Nina Zakharenko: It does, all right? Does, let's see, what did I name it here, my four_by_four. Does my four_by_four.num_wheels? Does it?
>> Speaker 2: No.
>> Nina Zakharenko: No, right, no.
>> Nina Zakharenko: Vehicle object has no attribute num_wheels.
>> Nina Zakharenko: My Car does, my Vehicle doesn't. And this is a good opportunity for me now if I wanted to make a motorcycle to make a new class that has the default num_wheels to be 2. And that really kinda cuts down on data duplication, makes this code a lot more composable, I want more like easier to maintain, right?
[00:09:59] If I had a method on Vehicle,
>> Nina Zakharenko: Let's say,
>> Nina Zakharenko: Is my fuel efficient, is_eco_friendly?
>> Nina Zakharenko: And I would take in self, and if the fuel = gas, we're gonna return False. Otherwise, we're gonna return True, and my self.fuel of course. And I know that self.fuel is always in my Vehicle.
[00:10:51] Even if I removed with this, it wouldn't matter because the fuel here is by default gas. So now I'm gonna go in, I'm going to reload this,
>> Nina Zakharenko: And then I'm gonna say, I'm gonna go back to my four_by_four.
>> Nina Zakharenko: And make a new instance, gonna make a new instance of my_subaru,
>> Nina Zakharenko: Subaru, crosstrek,
>> Nina Zakharenko: Does my four_by_four, can I call this is_eco_friendly, method on it? Yes. Can, right? Can I call it on my_subaru,
>> Speaker 2: No, because you didn't bring it in in super?
>> Nina Zakharenko: I didn't, but what did I do here by calling super().__init?
>> Nina Zakharenko: I called init on my Vehicle and my Car inherits from vehicle, so any methods available to my Vehicle will also be available on my Car.
[00:12:33] That's how we encourage code reuse. If I made a new motorcycle class that inherited from Vehicle, it would also have this is_eco_friendly method. So instead of making a motorcycle, and a car, and a four_by_four that all have their own version of this method, we cut down on code duplication, and put it in one place.
[00:12:57] Okay, the last topic here, I'm not gonna talk about very much I just wanna give you a heads up. Unlike in other languages, in Python, you can have multiple inheritance. So you can inherit from multiple different other classes at once. And things get a bit hairy, but one use case of this is something called a mix in.
[00:13:21] So a mix in might be a class that just has a method like this on it. And I don't care if my four_by-four is_eco_friendly. I'm driving it through the grass and mowing it down, and what do I care if it's gas or solar. So well, in the cases where I do care maybe like a car, I can have an additional class that I inherit from, it just have this method.
[00:13:52] So one of my favorite, one common used case for this you might see if you're declaring database tables in Python. You might have some mix-ins for something like a date column where you don't necessarily want. You want to have a date, a created on date on all of your objects just for compliance reasons.
[00:14:13] But you don't wanna have to say class vehicle dot date equals whatever. Class motorcycle dot date equals whatever. So you can just have a mix in class that will create that column for you, and provide all of the methods that you might need to use it.
>> Speaker 3: I've seen Python code that, an objects that don't, or classes that don't inherit from anything else, put the object keyword as the object that they inherit from.
[00:14:39] Instead of just saying the name, the class :, will have object after the class definition, is there difference?
>> Nina Zakharenko: Yeah, that is one of the differences between Python 2 and Python 3. In Python 3, you don't need to do that any more, i t's redundant, samples better than complex.
[00:15:01] You can still do it, and it's not a syntax error, you just shouldn't.