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 trial<noob />
17,062 PointsTrying to understand super()
Hello all. Im not fully understand wht super() does. In the pratice challenge we were asked to override the add_item method. Why i had to write the add_item method again and call super() if it's already done in the parent class? I couldn't write super().add_item(item)?
What is the reason behind it?
another question i have is about "self". evreytime i change attributes in the class i have to call self?
class Inventory:
def __init__(self):
self.slots = []
def add_item(self, item):
self.slots.append(item)
class SortedInventory(Inventory):
def add_item(self, item):
super().add_item(item)
self.slots.sort()
4 Answers
Jamison Habermann
11,691 PointsWhen redefining or overriding methods in classes, super() will extend that method to the new child class. Imagine if in the Inventory class, that add_item method was actually 100 lines of code. By calling super in the SortedInventory class, you are able to call all 100 lines of that method, then extend it which is what was done here.
As far as self goes, the short answer is yes, you would have to refer to it every time. I was just as confused as you were and honestly my best advice is to keep going because it made more sense as I kept using it.
<noob />
17,062 PointsThe self keyword is always used to refer to the current instance of the class? for example:
some_instance = Inventory()
some_instance.sword = "blue sword"
self refers to some_instance?
Chris Freeman
Treehouse Moderator 68,454 PointsExactly! In your example. self
would point to the same thing that some_instance
points at: an object in memory
Chris Freeman
Treehouse Moderator 68,454 PointsMore about self
. It is literally a reference to an instance of a class. This is the same type of reference as a label assigned to an instance:
# id is effectively the object location in memory
>>> help(id)
id(obj, /)
Return the identity of an object.
# create a basic class
>>> class Foo:
... def know_thy_self(self):
... """Return id of self"""
... return id(self)
...
# create instance of class
>>> f = Foo()
# check id of instance
>>> id(f)
140157928256792
# check id of self
>>> f.know_thy_self
140157928256792
So self
is no different than a label that also points to an instance!
bot .net asks: So self
is no different than a label that also points to an instance! I just want to clear it because it's really important. in the example, f is actually being used in the method ? f
is behind the scene refer to self?
You are correct that self
is no different than a label f
that also points to an instance! All labels point to objects in memory. In this case, self
and f
both point to the same instance. As a label, they are merely members of a namespace at different levels.
The label f
is at the top level __main__
and the label self
is at the f.know_thy_self
.
Using dir() you can see the namespace at any level:
Build the class
$ python
Python 3.6.3 (default, Oct 3 2017, 21:45:48)
[GCC 7.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> dir() # prints top level or __main__ namespace
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']
# Add a class Foo.
>>> class Foo:
... def know_thy_self(self):
... """Print 'self' and return id of self"""
... print(self)
... return id(self)
...
>>> Foo
<class '__main__.Foo'>
>>> dir() # __main__ now has Foo
['Foo', '__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']
>>> dir(Foo) # namespace of Foo. See method 'know_thy_self'.
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'know_thy_self']
>>> Foo.know_thy_self
<function Foo.know_thy_self at 0x7f589629ae18>
>>> dir(Foo.know_thy_self) # this is the unbound method in the class. It's unbound because there is no "self"!!
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
>>> Foo.know_thy_self.__self__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute '__self__'
Creating an instance
>>> f = Foo() # create instance f of Foo
>>> f
<__main__.Foo object at 0x7f58961b5a90>
>>> dir() # __main__ now has f
['Foo', '__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'f']
>>> dir(f) # namespace of f has "know_thy_self"
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'know_thy_self']
>>> f.know_thy_self
<bound method Foo.know_thy_self of <__main__.Foo object at 0x7f58961b5a90>>
>>> dir(f.know_thy_self) # there is __self__!!! It is bound to an instance
['__call__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__func__', '__ge__', '__get__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
>>> f.know_thy_self.__self__
<__main__.Foo object at 0x7f58961b5a90> # This label has the SAME value as f above
Running the method
>>> f.know_thy_self() #prints "self" which is same value a "f"
<__main__.Foo object at 0x7f58961b5a90>
140018452224656
The id
is in base 10. Converting to hexidecimal and you see that it is the same as the memory location:
>>> hex(f.know_thy_self())
<__main__.Foo object at 0x7f58961b5a90>
'0x7f58961b5a90'
As always, post back if you need more help. Good luck!!
<noob />
17,062 PointsI just want to clear it because it's really important. in the example, f is actually being used in the method ? f is behind the scence refer to self?
Chris Freeman
Treehouse Moderator 68,454 PointsSee expanded answer above.
Chris Freeman
Treehouse Moderator 68,454 PointsChris Freeman
Treehouse Moderator 68,454 PointsPromoting to Answer. Thanks for contributing to the community!!
Chris Freeman
Treehouse Moderator 68,454 PointsChris Freeman
Treehouse Moderator 68,454 PointsExactly! You want the best of both worlds: to use the same name as the parent's method and want to customize the behavior without having to rewrite all the code. The built-in function super() says "go run the parent's version, but come back here because I have more to do".
As for
self
, the class code explains how to construct an instance of the class. Theself
reference is set to the particular instance of the class that is currently being executed. This way theadd_item
method know in which instance ofSortedInventory
orInventory
to modify theslots
attribute.Post back if you need more help. Good luck!