Home > OS >  What does the super() point to on earth?
What does the super() point to on earth?

Time:10-02

In the post ,super() was described as: describe super()

super() looks at the next class in the MRO (method resolution order, accessed with cls.__mro__) to call the methods.   

Some material even give a more clear definition as: more clear definition on super()

def  super ( cls , inst ) : 
    mro = inst.__class__.mro( ) 
    return mro[mro.index( cls )     1 ]

Create a multiple inheritnce class struture as below:

class state():
    def __init__(self):
        pass

class event():
    def __init__(self):
        pass

class happystate(state,event):
    def __init__(self):
        print(super())
        print(super(happystate,self))

The mro list :

>>> happystate.__mro__
(<class '__main__.happystate'>, <class '__main__.state'>, <class '__main__.event'>, <class 'object'>)

The super() in happystate class will look at the next class in the MRO, it is state class in this status.

x=happystate()
<super: <class 'happystate'>, <happystate object>>
<super: <class 'happystate'>, <happystate object>>

Why super() in happystate class point to itself instead of the next class in MRO list----state?
If super() point to state,the output should be as:

x=happystate()
<super: <class 'state'>, <state object>>
<super: <class 'state'>, <state object>>

CodePudding user response:

It doesn't "point" to the same class, super is a class of its own:

>>> super
<class 'super'>

>>> class happystate(state,event):
...     def __init__(self):
...         print(super(), type(super()))
... 
>>> happystate()
<super: <class 'happystate'>, <happystate object>> <class 'super'>

So you can also use it outside the class:

>>> super(happystate)
<super: <class 'happystate'>, NULL>

But inside the class it has some special behavior, so let's save it as an instance variable so we can interact with it a bit more:

>>> class happystate(state,event):
...     def __init__(self):
...         self.s = super()
... 
>>> h = happystate()
>>> h.s.__self_class__
<class '__main__.happystate'>
>>> h.s.__thisclass__
<class '__main__.happystate'>                    # the class
>>> h.s.__self__                      
<__main__.happystate object at 0x7fa8a42642e0>   # the object of the class

But that still doesn't tell us much, so let's jump at the docs for super:

Return a proxy object that delegates method calls to a parent or sibling class of type. This is useful for accessing inherited methods that have been overridden in a class.

So at the end of the day super is there to help you access stuff from the parent class(es) without having to traverse the MRO yourself, which means cleaner code. Let's use this newfound knowledge and modify your code a bit:

class state():
    def __init__(self, x):
        print("state __init__", x)
        self.x = x

class event():
    def __init__(self):
        print("event __init__")

class happystate(state,event):
    def __init__(self):
        super(state, self).__init__()
        self.s = super()

Now let's try using the modified code:

>>> h = happystate()
event __init__        # surprise! It doesn't call `state` 
                      # (or its super - `object`) but the
                      # next in the MRO for `happystate`: `event`!

>>> h.s.__init__(3)   # calls state.__init__ (notice that we pass 1 argument)
state __init__ 3
>>> h.x               # state.__init__ received `h` as the `self` argument and updated it!
3

CodePudding user response:

super() returns an instance of a super class that tracks the current position in the MRO. When calling a method on a super instance, super looks up the next class in the MRO and calls the method on that class.

Maybe this will help:

class state():
    def __init__(self):
        print('state.__init__')
        print(super())
        super().__init__()

class event():
    def __init__(self):
        print('event.__init__')
        print(super())
        super().__init__()

class happystate(state,event):
    def __init__(self):
        print('happystate.__init__')
        print(super())
        super().__init__()

print(happystate.mro())
x = happystate()

Output:

[<class '__main__.happystate'>, <class '__main__.state'>, <class '__main__.event'>, <class 'object'>]
happystate.__init__
<super: <class 'happystate'>, <happystate object>>  # currently in happystate of happystate object
state.__init__                                      # state is next
<super: <class 'state'>, <happystate object>>       # now in state of happystate object.
event.__init__                                      # event is next
<super: <class 'event'>, <happystate object>>       # now in event of happystate object

This also illustrates that when using inheritance, all classes in the tree need to use super(). Even though event doesn't have a base class, lack of super().__init__() would never call state.__init__ when creating a happystate.

  • Related