Python Object-Oriented Python Inheritance Multiple Superclasses

clarify somethings about MRO of this video

so here in this video when we create an instance of Thief Class.

The first __init__ to be called is "Sneaky" __init__ because on the top of MRO for the Thief Class is Thief Class itself , and since Thief class doesn't have __init__ method The MRO falls back to the next class in it's chain of commands which is "Sneaky" class which have __init__ method so "Sneaky" __init__ called First and our instance acquires (sneaky attribute) , then Agile __init__ called second and our instance acquires (agile attribute) , then Character __init__ called last and our instance acquires (name attribute) what super() function do here is that it gets *args and *kwargs code all the way down from Character class (Sneaky supers Agile and Agile supers Character)

did i get it right ? i know i said much , but i hope someone can validate how i get it

[MOD: added ` around __init__ to preserve characters]

2 Answers

Chris Freeman
MOD
Chris Freeman
Treehouse Moderator 59,027 Points

Yes. You have it correct! Execution would stop at the first __init__ method without a super() call.

Jay Reyes
Jay Reyes
Python Web Development Techdegree Student 15,935 Points

A simple explanation, thank you both. I'm afraid the instructor failed to mention that calling multiple classes in the creation of an instance creates a hierarchy of parenthood.

So if it was

class Thief(Agile, Sneaky, Character):
    def pickpocket(self):
        return self.sneaky and bool(random.randint(0, 1))

We would have:

  • Agile as the child of Sneaky
  • Sneaky as the child of Character

I guess Thief is the child of Agile?

Chris Freeman
Chris Freeman
Treehouse Moderator 59,027 Points

I would say they are more like “ordered co-parents” rather a hierarchy of parents. The parents classes Agile and Sneaky act more like “add-ins” that modify the parent class Character. The add-ins can be listed with either one first. Add-ins are not typically intended to be a sole parent class.

I had a really tough time with this conceptually, and it took me a little while to get my arms wrapped around the content. I embedded a bunch of print statements into my code to help me follow the program flow.

Using the same order of super classes as Kenneth's code example (Agile, Sneaky, Character), I created an instance of Thief and watched the control cascade from Agile to Sneaky to Character, and then back again. It helped me track what was going on, and helped me to further understand the great information provided by Chris and others. I thought I would post my output just in case it might help someone else. Cheers!

With the exception of the first two lines, this is all output from print() statements that I added inside my Agile, Sneaky, and Character classes:

from thieves import Thief
p1 = Thief(name="Darrius", sneaky=False)

Now inside the Agile __ init __ method.
-- Doing the super() call from inside Agile.
Now inside the Sneaky __ init __ method.
-- Doing the super() call from inside Sneaky.
Now inside the Character __ init __ method.
Setting self.name inside the Character __ init __ method.
Darrius
Setting self.sneaky inside the Sneaky __ init __ method.
False
Setting self.agile inside the Agile __ init __ method.
True

Derrick Thomin
Derrick Thomin
10,300 Points

Since the contents of kwargs at different points is what was tripping me up, I did a similar thing as ericfromportland did in the above post (thanks for the good idea!). Posting here in case it helps anyone this all happens right after this line of code is called in play.py: derrick = Thief(name="derrick", sneaky=False)

----------                                                                                                                                                                    
Right Before super call in Agile                                                                                                                                              
agile: True                                                                                                                                                                   
Args: ()                                                                                                                                                                      
Kwargs: {'name': 'derrick', 'sneaky': False}                                                                                                                                  
----------                                                                                                                                                                    
----------                                                                                                                                                                    
Right before super call in Sneaky                                                                                                                                             
sneaky: False                                                                                                                                                                 
Args: ()                                                                                                                                                                      
Kwargs: {'name': 'derrick'}                                                                                                                                                   
----------                                                                                                                                                                    
----------                                                                                                                                                                    
Right After __init__ super call in Character                                                                                                                                  
Name: derrick                                                                                                                                                                 
Kwargs: {}                                                                                                                                                                    
----------                                                                                                                                                                    
character | name==derrick                                                                                                                                                     
----------                                                                                                                                                                    
Right After super call in Sneaky                                                                                                                                              
sneaky: False                                                                                                                                                                 
Args: ()                                                                                                                                                                      
Kwargs: {'name': 'derrick'}                                                                                                                                                   
----------                                                                                                                                                                    
----------                                                                                                                                                                    
Right After super call in Agile                                                                                                                                               
agile: True                                                                                                                                                                   
Args: ()                                                                                                                                                                      
Kwargs: {'name': 'derrick', 'sneaky': False}                                                                                                                                  
----------
Chris Freeman
Chris Freeman
Treehouse Moderator 59,027 Points

Well done Derrick Thomin! That’s also what I did to really understand it.

Another key insight is, at each method called, the receiving parameter *args and **kwargs aren’t the same as the calling *args and **kwargs arguments. Instead, the receiving ones are recreated from the left-overs after the positional and keyword parameters in the called method have been assigned.