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 trialJC Canapi
2,097 PointsPython OOP classes Sneaky and Agile super() clarification
Hi,
I would like to get clarification with regards to the use of super() in the attributes.py. Why do we need super() below each init we are not referring to another super class? Or am I missing something?
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)
(MOD: Just updated the code formatting so it's easier to read. See the Markdown Cheatsheet below the text box when writing, for how to do the formatting. Don't worry, it's easy!)
1 Answer
Chris Freeman
Treehouse Moderator 68,457 PointsGreat question! The super()
function refers to calling the next parent class in the Method Resolution Order (MRO). But wait, you say, Sneaky
and Agile
do not have an parent classes. Even if there are no classes listed, all classes are assumed to inherit from the base class object
.
>>> class foo:
... def __init__(self, *args, **kwargs):
... super().__init__(*args, **kwargs)
...
>>> f = foo()
>>> foo.__class__.__mro__
(<class 'type'>, <class 'object'>)
In this case, the super()
call in foo.__Init__()
would call object.__init__()
which is basically a do nothing function at the base level that does not accept arguments. This means that any arguments not consumed by the Sneaky
or Agile
__init__
method would get passed to object.__init__()
and an error would be raised:
>>> 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
...
>>> s = Sneaky(True)
>>> s
<__main__.Sneaky object at 0x7f547234d198>
>>> s.sneaky
True
>>> s = Sneaky(True, "bob")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in __init__
TypeError: object.__init__() takes no parameters
Due to the presence of super().__init__(*args, **kwargs)
in both Agile
and Sneaky
, and since any arguments passed on to object.__init__()
will raise a TypeError
, then the classes Agile
and Sneaky
can only safely be used as part of a multiple inheritance chain where the last class on the chain either,
- handles all
*args
and**kwargs
passed in, or - does not call
super
.
So the bottom line is super()
is needed in Agile
and Sneaky
precisely because both are intended to be used solely as "MixIn" (see What is a MixIn) classes to amend the behavior of another class on the inheritance list. In this case, they are both used to add attributes and methods to the base Character
class.
It is standard convention of an "MixIn" class to include a super().__init__(*args, **kwargs)
statement in the __init__
method so that all extra arguments are passed down the MRO chain to be used or passed further along, as needed, by subsequent classes.
Post back if you have more questions. Good luck!!
JC Canapi
2,097 PointsJC Canapi
2,097 PointsThanks Chris, this clarifies the use of super() for me. :)