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 trialSimon Amz
4,606 PointsCalling super class inheritance
Hi, I don't understand why in the Agile and Sneaky classes, we don't inherit from Character. Indeed, the declaration is :
"class Agile:" and "class Sneaky:" instead of "class Agile(Character):" and "class Sneaky(Character):"
in this case, when you're using "super()" with def __init__
, which is the super class it inherit from as the class is not specified?
5 Answers
Chris Freeman
Treehouse Moderator 68,441 PointsGood question! The classes Agile
and Sneaky
certain could have been declared as inheriting from Character
. It still would work but it starts to become less than clear what the intentions are.
class Agile(Character):
class Sneaky(Character):
class Thief(Agile, Sneaky):
# or
class Thief(Agile, Sneaky, Character): # still works
By having them both inherit from Character
, it implies that one might wish to create an Agile
instance or a Sneaky
instance, but this isn't the goal of this code. Kenneth wished to create add-in (or "mix-in") attributes that could be used generically to add to any class.
An extension would be if there was a Monster
class, then the Agile
and Sneaky
could be reused to add those attributes to a specific monster class, as opposed to creating a monster version of "agile" that inherited from Monster
instead of Character
.
Given the original code class Thief(Agile, Sneaky, Character):
The super().__init__()
order is the same as the Method Resolution Order (MRO):
>>> from thieves import Thief
>>> Thief.__mro__
(<class 'thieves.Thief'>, <class 'attributes.Agile'>, <class 'attributes.Sneaky'>, <class 'characters.Character'>, <class 'object'>)
You might think the MRO would be:
Thief --> Agile --> object --> Sneaky --> object --> Character --> object
But since Character
depends on object
, the earlier object
references are removed and only the last object
is retained:
Thief --> Agile --> Sneaky --> Character --> object
Post back if you have more questions. Good luck!
Edit: Hara and Pete ask: why use super()
in Agile
and Sneaky
?
When using multiple inheritance (inheriting from more than one class) all references are resolved by looking in the local code first, then one by one each of the inherited classes are checked for the reference. Once a reference is found it is used immediately and the search stops.
The use of super()
indicates to continue searching for the indicated reference down the Method Resolution Order (MRO) for more code to execute.
In the case of creating a new instance, the __init__
method is called. If the Thief
class had an __init__
method without a super() call, execution would stop there. If there isn't a local __init__
then the search would continue with the inherited classes.
By using super()
in the Agile
and Sneaky
class you guarantee that __init__
method in all inherited class will get an opportunity to be executed.
Edit: Kafe Hezam asks: why not remove *args
from both Agile
and Sneaky
?
In this case, since no positional arguments are used *args
could be removed. However, not removing the generic positional placeholder *args
allows the attribute classes Agile and Sneaky to be used with other classes besides Character where positional arguments may be in use. It’s common practice to include both *args
and **kwargs
to allow greater reuse.
Hara Gopal K
Courses Plus Student 10,027 Pointsunderstood to some extent, but still not so clear. the question is, what are we trying to achieve by using the super() in Sneaky and Agile classes. In other words, what are we inhering, and from where, and why ?
thanks for some clarifications hara
Chris Freeman
Treehouse Moderator 68,441 PointsHara Gopal K, great question. I've expanded my answer above. Post back if you have more questions.
Pete P
7,613 PointsI have the same question. In the previous examples, it was obvious to me what super() was being used for. In this video I do not see the purpose for using super() in the Sneaky and Agile class.
Chris Freeman
Treehouse Moderator 68,441 PointsPete P, great question, I've expanded my answer above. Post back if you have more questions.
Pete P
7,613 PointsThank you Chris! I found your's and ds1's answers to this question very helpful!
Much appreciated.
Bob Pickles
1,363 PointsThey aren't supposed to be inheriting from Character, they are inheriting from object. Keep in mind that all classes inherit from object. In python 3 this inheritance is implicit so Sneaky() is the same as Sneaky(object)
Reference: https://stackoverflow.com/questions/4015417/python-class-inherits-object
Kafe Hezam
11,070 PointsChris Freeman, When Kenneth explicitly sets name to equal "Kenneth" which gets store into **kwargs since its a keyword argument. So if I delete *args from both classes Agile and Sneaky It'l give me the same answer as if it was not deleted. Then what's the point of keeping *args? :))
Chris Freeman
Treehouse Moderator 68,441 PointsGreat question! The short answer is using both *args
and **kwargs
allows for wider reuse of code. See expanded answer above.
MoatazBellah Ghobashy
9,518 PointsMoatazBellah Ghobashy
9,518 PointsThanks a lot :)