Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialTyler Wells
Python Development Techdegree Student 2,678 PointsMRO in superclasses/sibling classes and super()
So the MRO first and foremost reads left to right (goes through Agile, Sneaky then Character classes)?
Then by doing that, and through using super() in the __init__
we're then sending from the Agile class the attribute that the thief is agile to the Sneaky class which then sends both agile and sneaky attributes to the character class? Thats the jist of super()? But I thought in order for super to work we had to have the exact same function/method in the subclass as the superclass (taking out the self parameter), no?
1 Answer
Chris Freeman
Treehouse Moderator 68,441 PointsGreat questions!
From Tyler:
The MRO first and foremost reads left to right (goes through Agile, Sneaky then Character classes. Correct!
Then by doing that, and through using super() in the __init__
we're then sending from the Agile class the attribute that the thief is agile to the Sneaky class which then sends both agile and sneaky attributes to the character class? Almost correct. The beauty of using *args
and **kwargs
is they only get assigned the “leftover” attributes. Since Agile defines agile it is not passed on to Sneaky and, since Sneaky defines sneaky it is not passed on to Character.
That’s the jist of super()? think of super()
as a temporary redirect to a method of the same name somewhere in the MRO. The first method with the same name is run. It’s only by including additional super() calls in subsequently reached methods that any chaining occurs. Otherwise, execution would stop at the first method without a super().
But I thought in order for super to work we had to have the exact same function/method in the subclass as the superclass (taking out the self parameter)? Correct. If super().__some_method__()
is called, then the method __some_method__
must exist somewhere on the MRO or an AttributeError
will be raised.
From Jay:
why is super() in sneaky and agile init when both are the super class of thief? Execution will stop at the first parent method that does not contain super().
Does character become the parent class for sneaky, agile, and thief because it is "final"? Sneaky and Agile only have the base object
class as a parent. The three parent classes are better described as ordered co-parent classes.
I expect [method Thief.pickpocket] to contain an init that contains super(). the __init__
methods are only called at the initialization of the class instance. The method pickpocket
would only contain a super() call if:
- a method of the same name existed in one of the parent classes listed in the MRO, (or a parent of a parent, etc.), and
- you wanted the parent version of the method to also be run.
Food food thought: The super() call can be the first line, a middle line, or the last of a method depending on when you want the parent code to run. Putting super() first allows you to modify the parent’s actions, putting super() last allows you to modify parameters before they’re sent to the parent, putting in the middle of a method allow you to do both.
Post back if you need more help. Good luck!!!
Anthony Grodowski
4,902 PointsHi Chris!
Could you please explain to me what is chaining?
I also don't fully get this sentence - "It’s only by including additional super() calls in subsequently reached methods that any chaining occurs. Otherwise, execution would stop at the first method without a super()."
"The beauty of using *args and **kwargs is they only get assigned the “leftover” attributes. Since Agile defines agile it is not passed on to Sneaky and, since Sneaky defines sneaky it is not passed on to Character." - so does it mean that after the execution Agile Class will also have sneaky attribute and Character Class will have sneaky and agile attribute?
"Sneaky and Agile only have the base object class as a parent." - and lastly - what object is that and why do we call it (I've seen your previous answer on a similar topic in which you said that it's a do-nothing class - so why do we use it? To be able to use super to continue chaining?) ?
I'd be very grateful for you answer! Cheers, Antek!
Chris Freeman
Treehouse Moderator 68,441 PointsCould you please explain to me what is chaining? “Chaining” is not an actual term, but a metaphor I use to mean flowing execution through each of the parent classes in turn.
I also don't fully get this sentence - "It’s only by including additional super() calls in subsequently reached methods that any chaining occurs. Otherwise, execution would stop at the first method without a super()."
super()
says only run the method from the first parent (or the next parent in the MRO). Execution stops there unless another super
is encountered to keep execution going to the next parent on the MRO.
"The beauty of using *args and **kwargs is they only get assigned the “leftover” attributes. Since Agile defines agile it is not passed on to Sneaky and, since Sneaky defines sneaky it is not passed on to Character." - so does it mean that after the execution Agile Class will also have sneaky attribute and Character Class will have sneaky and agile attribute? The base classes Agile
will have agile
, Sneaky
will have Sneaky, but Character
will have neither. Only the instantiation of Thief
will have all the attributes. Keep in mind that the executing code is from the parent classes but is being executed in the Thief
instance.
"Sneaky and Agile only have the base object class as a parent." - and lastly - what object is that and why do we call it (I've seen your previous answer on a similar topic in which you said that it's a do-nothing class - so why do we use it? To be able to use super to continue chaining?) ? The base class object is inherented from automatically.
It has the methods that are common to all instances of Python classes.
In the cases of multiple inheritance where every parent inherits from object
, the MRO is dynamically structured such that object
occurs exactly once and is always the last in the order.
You can see the MRO of Thief
using:
print(Thief().__class__.__mro__)
I'd be very grateful for you answer! Cheers, Antek! You are very welcome!
Anthony Grodowski
4,902 PointsThanks! Answer professional as always:)! So does it mean that as long as Sneaky
and Agile
don't have methods that depend on each other (for example in Sneaky
there's a method that is neccessary for some Agile
method to run) and both have super()
and Character
doesn't, it doesn't matter if it's Thief(Agile, Sneaky, Character)
or Thief(Sneaky, Agile, Character)
.
Also I'd like to make sure that I got super()
right. So basically it's a redirect from a Child class to a Parent class, which can be 'chained'. For example in Thief(Agile, Sneaky, Character)
first of all, ALL of the Agile
mehods are being run, then super()
in Agile
redirects to Sneaky
in which the code BELOW super()
which is indented in super()
code block is being run (in this case self.sneaky = sneaky
) and Sneaky
redirects to Character
, which doesn't contain super()
, so the execution stops after WHOLE Character
code is being executed.
If I'm right, super()
has 2 fuctions - one is to redirect to an another class and the second is to overwrite a piece of code from the child class by a piece of code of the parent class code Did I get all of that right?
Chris Freeman
Treehouse Moderator 68,441 Points... it doesn't matter if it's Thief(Agile, Sneaky, Character) or Thief(Sneaky, Agile, Character). correct!
For example in Thief(Agile, Sneaky, Character) first of all, ALL of the Agile mehods are being run, then super() in Agile redirects to Sneaky in which the code BELOW super() which is indented in super() code block is being run (in this case self.sneaky = sneaky) and Sneaky redirects to Character, which doesn't contain super(), so the execution stops after WHOLE Character code is being executed. This is close. Not all methods in Agile
run. Only the method called and it’s equivalent called by super()
are run. once the super()
call is complete, the execution returns to the call method. For __init__
the flow goes:
-
Thief.__Init__
pre-super ->Agile.__init__
pre-super ->Sneaky.__init__
pre-super ->Character.__init__
->Sneaky.__init__
post-super ->Agile.__init__
post-super ->Thief.__init__
post-super
If I'm right, super() has 2 fuctions - one is to redirect to an another class yes! and the second is to overwrite a piece of code from the child class by a piece of code of the parent class code the overriding is more the child is overriding the parent’s code. An override I’d not always necessary. The parent’s code might only be augmented or extended.
Jay Reyes
Python Web Development Techdegree Student 15,937 PointsJay Reyes
Python Web Development Techdegree Student 15,937 PointsI'm confused as well...
class Thief(Agile, Sneaky, Character):
From the above: 1) why is
super()
insneaky
andagile
__init__
when both are the super class ofthief
?2) Does
character
become the parent class forsneaky
,agile
, andthief
because it is "final"?Like you seem to say ( tell me if otherwise), I expect ...
... to contain an
__init__
that containssuper()