Python 3, an Illustrated Tour Transcripts
Chapter: Classes and inheritance
0:01 Let's talk about the new behavior for super in Python 3. This comes from Pep 3135.
0:10 If you're not familiar with super, super is a mechanism that we use in Python to get access to a parent class. So if you have some method in a subclass
0:21 and you want to call the parent class, you can call super and then pass in the arguments to the parent method and get access to it that way.
0:30 In Python 2 this was a little convoluted and a little confusing. So the syntax in Python 3 is cleaned up a little bit and we'll talk about that.
0:38 Just as a review, a couple of things that you might want to do when you're doing object-oriented programming and you're subclassing things.
0:45 So if you've got a subclass, you can defer to the parent class for a method. To defer to a parent class, you don't have to do anything.
0:51 You don't even have to implement the method. You just leave it there and when you call the method on the subclass, it will call the parent class.
0:58 You can override a method or overload and in order to do that, you just implement the method in the subclass.
1:05 And another thing you can do is specialize or take advantage of the parent implementation, but also add your own implementation to it
1:13 and super allows us to do that. Here's what not to do, if I've got a class called animal, I've got a subclass of animal called cat,
1:20 both of these Implement a method called talk for animal talk just return sound and for cat talk does a little bit more,
1:28 it's going to call the parent method talk and then it's going to add and purr onto the end of that.
1:36 In the cat talk method, you'll note that we call the parent class. We call animal.talk to get sound, the string sound back.
1:44 And then we're going to stick that into this placeholder and return sound and purr at the bottom here. Now, this is what you don't want to do.
1:52 You don't want to explicitly call animal, rather we want to do something like this where instead of calling animal we call super
1:59 and you invoke super and that will return the parent class and call talk on the correct parent class.
2:06 So this is how we do want to do that, and Python is smart enough to know
2:10 that when super is called within a method that it will find the correct class to call it on.
2:16 Here's a little drawing that shows what's going on under the covers. On the left hand side here, we've got the code for animal
2:23 and on the right hand side we've got a representation of what's going on under the covers. We've got some objects here, so here's one object
2:31 and it has a variable called Animal that's pointing to that object,
2:36 inside of that object, there's an attribute called talk that's pointing to another object. and this is a function down here.
2:42 This is what's going on in the virtual machine under the covers. Again, in Python everything is an object
2:47 and this is the representation that Python would do. Obviously there are going to be other attributes in here that we're not showing in this case.
2:55 We also note that every object has an ID and you can inspect that ID by calling the ID function and objects will also have a type as well.
3:03 So when we subclass animal we're going to make another object called cat and it's going to have a reference to the parent.
3:12 It will look something like this. So here we have our prior animal variable and we're going to make a new variable called cat,
3:18 cat is a subclass of animal and if it's a subclass it's going to have an attribute called __bases__ __bases__ is actually a tuple,
3:26 in this case, we're just showing it that it refers back to the animal parent class here
3:30 and we'll note that animal has a talk method and cat has its own talk method.
3:36 Again, this is the representation of what's going on inside the Python virtual machine, but we can see that there's a relationship
3:44 between cat and animal due to our bases attribute. We could simplify this a little bit and we could say that a cat is an animal
3:52 and the relationship looks like this. This will be useful when we talk about method resolution in a diamond structure.
3:59 There are a couple of useful things for using super one is if you're refactoring your classes and changing the names of them,
4:06 you don't need to push that code for refactoring into the specialization calls. You can just leave super in there and it will do the right thing.
4:14 It's also useful when you have multiple inheritance. There's this __mro__ attribute or mro method that you can call
4:22 that will resolve the order in which classes are called and super does the right thing there.
4:28 One thing to be aware of is that you need to be consistent and only use super, you can't like I said before
4:33 explicitly hard-code the parent class in there. If you do that, then your other guys that are using super aren't going to work.
4:41 So you want to make sure you only use super. Let's talk about method resolution order a little bit.
4:46 Here's a class A and a class B, and then we have a class C and a class D. If we're going to draw these in our little diagram here
4:54 it would have A and it would have B. And then we have C here, C is an A, it subclasses A and then we have D, and D derives from both C and B.
5:11 So this would be our hierarchy over here. And we can inspect the method resolution order the mro by calling the mro method
5:19 and we see that we get D first, then C, then A, then B, and then object. Here's a diagram showing that, this is the same diagram that I had before
5:31 but we can see if we want to resolve a method on D first we will look on the D class, if that's not there, we'll look on C
5:39 and because C is in A we're going to look on A, and finally, if none of those guys implement, it will look on B. That's the method resolution order,
5:46 pretty straightforward when you don't have diamonds. The method resolution order falls what's known as the C3 linearization algorithm
5:55 and that's depth first generally, we saw an example of that in the last example, but if you have a diamond pattern, we change it a little bit
6:03 and we use the last occurrence of repeated parents. Let's see an example of how this works.
6:08 So here I have a diamond pattern, I've got a class A that is a subclass of dict,
6:16 So at the top here would have dict and then would have A, the subclass is that, we also have B, the subclass is dict
6:24 and then we have C, that subclasses A and we have D, that subclasses C and B. So this is called a diamond pattern
6:35 because you'll see that it has something at the top and something the bottom and it branches out to the sides here.
6:40 Here's the method resolution order, here's how we do it.
6:43 We say the linearization of D is equal to D plus the linearization of its parent which is C and B. So I'll just draw what we have before here.
6:54 We had dict and we had A and B, and we had C and D. In order to linearize this, or find which classes we're going to look up our methods on,
7:12 first we need to start with D and then we're going to look at the linearization of C and then the linearization of B.
7:20 So D comes down and since D isn't repeated, we'll use D. The linearization of C is C plus the linearization of A
7:30 and the linearization of B is B plus linearization of dict. Let's expand that a little bit more. So we're going to have D plus C,
7:41 the linearization of A which is A plus the linearization of dict plus B plus the linearization of dict
7:48 and since we've expanded all these out, we have all the classes here, we'll note that there's a repeat, we have this dict here
7:55 which would just resolve to dict so both this guy and this guy would resolve to dict
8:00 and because this is a repeat, we're going to get rid of the first one here. And so the final linearization is first we'll go to D, then we'll go to C,
8:10 then we'll go to A, then we'll go to B, and finally we'll go to dict. That's how the algorithm works here.
8:18 And if you inspect the mro method you'll see that that is indeed the case, we get D, C, A, B, dict and then object.
8:25 Object here is because every object is a subclass of object and the result looks something like this
8:31 which is hard-coded graph of what we just drew out. In here we learned a little bit about super, the main things to remember about super is
8:39 if you start subclassing things, you want to always use super don't explicitly call parent classes
8:45 and super will do the right thing if you're calling super, so super is a great tool to have and make use of it.