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 trialMichal Janek
Front End Web Development Techdegree Graduate 30,654 PointsWhy do attributes classes also have super().__init__() funcs?
From what I have gathered so far from this renewed course we use super() in order to initialize init function of parent class from which the one we are working on inherits. But attributes do not inherit any so why?
class Sneaky:
sneaky = True
def __init__(self, sneaky=True, *args, **kwargs):
super().__init__(*args, **kwargs)
self.sneaky = sneaky
def hide(self, light_level):
return self.sneaky and light_level < 10
class Agile:
agile = True
def __init__(self, agile=True, *args, **kwargs):
super().__init__(*args, **kwargs)
self.agile = agile
def evade(self):
return self.agile and random.randint(0, 1)
3 Answers
ds1
7,627 PointsHi, Michal- I was wondering the same thing. Perhaps by me posting this, it will bring your question up in the queue again and someone more knowledgeable can answer it definitively for us. But I'll try to answer you question based on what I've learned after some research:
1) even though Sneaky and Agile both do not explicitly define a parent or super class, they both have one... it's called "object". To my knowledge, everything in Python goes back to a built-in object class. If it didn't, using "super().[etc]" inside either class would result in an error when used.
-->fyi, technically, you don't have to use "super()" if you want to call a parent's methods inside a child's class.... You can just use the parent's class name. Say a class named Word was a child of a class named Letter. Instead of writing "super().init([arguments])" in Word class, you could write "Letter.init(self, [arguments])" Note the use of "self" in the latter. A reason why "super()" is favored more than the latter example is that it makes the child class more dynamic (ex. what if you changed Letter or the inheritance hierarchy? You'd have to change the reference in the child class.) By using super(), I guess your code is not as 'tightly coupled' as Kenneth talks about.
2) In multiple inheritance (vs. single inheritance), super() is not just a link to a child's parent... it's a link to the child's entire family tree. So the MRO (method resolution order) of the Thief() class is: Thief, Sneaky, Agile, Character, [object]. From nearest in relationship to furthest away. So, if you typed in "thief1 = Thief(name='badguy', weapon='gun'), then Python passes these parameters to the Thief's init function first, then it goes to Sneaky, then to Agile, then to Character, then to object. At the end of all this, we want thief1.name = 'badguy' and thief1.weapon = 'gun'. But notice, in our example, based on the code shown in the video, .name doesn't get assigned until python gets to the Character class. And while we've made no mention of .weapon, the Character class takes care of this as well with our handy kwargs.items() and setattr code... which is great because no parameter should get to the object class (because it's init doesn't take any arguments, I think) or an error is thrown.
-->BUT, Character will never get a chance to assign .name and .weapon properly if the respective parameters do not pass through Thief, Sneaky and Agile first. That is why each of these three classes has a **kwargs argument AND why each of these classes use super()... even Sneaky and Agile. If Sneaky and Agile didn't use super() then your parameters could not continue down the chain to Character... which is why if you took out the super() reference in Sneaky or Agile, your code will throw an error.
So the kwargs dictionary we create and pack (with name='badguy' and weapon='gun'), flows in to the first class in the MRO, and that class takes any applicable parameters out of that dictionary via its init function if applicable, then effectively passes what remains of kwargs (using the "super().init" bit of code) to the next class in the MRO for that class's init function, and so on. By the time kwargs gets to the object class, it's empty, which is why an error is not thrown.
Anyway, that's my take on the video's code example using multiple inheritance and my attempt to answer your question... until someone more knowledgeable tells me differently : ) Hope this helps! D.
Chris Freeman
Treehouse Moderator 68,441 PointsNice answer ds1! Thanks for the mention.
I have a few supporting comments and clarifications. Which might be redundant but in my wording.
While Agile
and Sneaky
do not have inherited classes (other than the default object
), they are intended to be used as mixin classes along with other base classes and not on their own. Trying to use one of these mixin on its own would raise an error because, as ds1 mentioned, object.__init__
does not accept arguments.
a = Agile() # fails
The super().__init__()
in each mixin will look down the MRO chain looking for the first __init__
found. Since both Agile
and Sneaky
utilize super()
, eventually Character.__init__
will be reached if Character
is the last class in the MRO.
Without the calls to super()
, the init process would stop at the first mixin __init__
and not continue down the chain.
Also, notice that Thief
has no __init__
method. This means it will start the init process with the first __init__
found in the inherited classes.
Not sure if I added anything different that what was said already.
Post back if you need more help. Good luck!!!
ds1
7,627 PointsThanks, Chris! I really appreciate you confirming what I thought/hoped was the answer to Michal's question. And thanks for pointing out that Thief() does not have an init function... I don't want misinformation in my answer to confuse any future readers! D.
Michal Janek
Front End Web Development Techdegree Graduate 30,654 PointsI had easier time reading through this but ds1 really nailed it.
Rui Xu
11,245 PointsJust check from my local environment, a = Agile() doesn't fail, but a = Agile(name='xxx') does, I believe it is a typo in your comments. :) But I get your points anyway. Thanks all for the sharing, it clears my doubts!
Quinton Dobbs
5,149 PointsHopefully this post isn't too old, but if I am to understand correctly, super() passes onto whatever is next in the MRO and only passes to the object when it last in the MRO. And in this example nothing is passed to the object class because Character doesn't use super(). Is that correct?
Chris Freeman
Treehouse Moderator 68,441 PointsQuinton, you are correct!
Andrew McLane
3,385 PointsI thought using super() allowed us to use a method from a parent - I don't understand what we mean by "passing" things on to the parent classes.
Chris Freeman
Treehouse Moderator 68,441 PointsYou are correct, in the general case, that super()
grants access to a method the parent class.
The "passing" occurs in the expanded case of multiple inheritance where each parent also utilize super()
for the specific method overriden by the derived class. When each parent also uses super()
, each subsequent parent's method is called in a chained fashion while passing the unconsumed arguments to the next parent.
The use of *args, **qwargs
In the parent methods allow the passing along the unknown arguments.
ds1
7,627 Pointsds1
7,627 PointsChris Freeman
Eddy Hood
10,154 PointsEddy Hood
10,154 PointsSo awesome! This explanation was a life saver. Thank you.
Michal Janek
Front End Web Development Techdegree Graduate 30,654 PointsMichal Janek
Front End Web Development Techdegree Graduate 30,654 PointsThank you I am referencing this answer a lot :D
Jaxon Gonzales
3,562 PointsJaxon Gonzales
3,562 PointsThis clarified so much thanks!
Brady Huang
16,360 PointsBrady Huang
16,360 PointsOh my god, it's awesome explaination.
Ryan Cross
5,742 PointsRyan Cross
5,742 PointsThe video on this subject left me pretty lost. Your explanation cleared up everything quite nicely. I think that's some helpful criticism of the video. Look at all the responses that felt the same way.