Python Forum
super() and order of running method in class inheritance
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
super() and order of running method in class inheritance
#1
hi in code:
'''
from:https://stackoverflow.com/questions/64740117/how-method-resolution-order-mro-is-working-in-this-python-code
title of the above page: How Method Resolution Order (MRO) is working in this Python code
'''

class parent:
    def __init__(self):
        self.a=2
        self.b=4
    def form1(self): 
        print("calling parent from1")
        print('p',self.a+self.b)
 
class child1(parent):
    def __init__(self):
        self.a=50
        self.b=4
    def form1(self):
        print('bye',self.a-self.b)
    def callchildform1(self):
        print("calling parent from child1")
        super().form1()
 
class child2(parent):
    def __init__(self):
        self.a=3
        self.b=4
    def form1(self):
        print('hi',self.a*self.b)
    def callchildform1(self):
        print("calling parent from child2")
        super().form1()
 
class grandchild(child1,child2):
    def __init__(self):
        self.a=10
        self.b=4
    def callingparent(self):
        super().form1()
        
print(f" grandchild.__mro__ is {grandchild.__mro__}")
g=grandchild()
g.callchildform1()
print(f"child1.__mro__ is {child1.__mro__}")
the output is:
Output:
grandchild.__mro__ is (<class '__main__.grandchild'>, <class '__main__.child1'>, <class '__main__.child2'>, <class '__main__.parent'>, <class 'object'>) calling parent from child1 hi 40 child1.__mro__ is (<class '__main__.child1'>, <class '__main__.parent'>, <class 'object'>)
according to MRO of the class grandchild, the line g.callchildform1() causes to callchildform1's method in classchild1 class is called and in this method there is super().form1() (line 22).
now we are in the class child1 and for the mro of this class, the form1 method of parent class must be called. but the form1 method of class child2 is called.
explain to me why Python acts as this.
As in the docstring of this code has been written, this subject has been discussed in the given address, but the issue is ambiguous to me still.
thanks
Reply
#2
(Feb-01-2024, 07:21 AM)akbarza Wrote: explain to me why Python acts as this.
This is explained in the documentation of super
Documentation Wrote:The search starts from the class right after the type.

For example, if __mro__ of object_or_type is D -> B -> C -> A -> object and the value of type is B, then super() searches C -> A -> object.
In your case, the __mro__ of g is grandchild -> child1 -> child2 -> parent -> object So in child1, super() finds child2 before parent.
« We can solve any problem by introducing an extra level of indirection »
Reply
#3
Quote:As in the docstring of this code has been written, this subject has been discussed in the given address, but the issue is ambiguous to me still.
What part confuses you? Maybe an example with more depth will help?
class A:
pass

class B:
pass

class C:
pass

class D:
pass

class E(A, B):
pass

class F(C, D):
pass

class G(E, F):
pass

print(*G.__mro__, sep="\n")
Output:
<class '__main__.G'> <class '__main__.E'> <class '__main__.A'> <class '__main__.B'> <class '__main__.F'> <class '__main__.C'> <class '__main__.D'> <class 'object'>
Which we can draw like this:
Output:
A B C D \ / \ / E F \ / G
We traverse the mro graph giving preference the left node (first superclass). If we don't find what we need in the left branch, back up one level and try the next superclass. So if we cannot find the method we are looking for in A, back up to E and try the next superclass of E which is B. If we can't find it there we have to back up to G and check the next superclass, F. The search order is Look local, then look at leftmost super. When you reach object, back up and look at next super.

In practice, using inheritance like this will quickly drive you insane, and multiple inheritance examples in Python are rare compared to single inheritance. But the mechanism is in place for you to drive yourself insane if that's what you want to do.
Reply
#4
(Feb-01-2024, 07:54 AM)Gribouillis Wrote:
(Feb-01-2024, 07:21 AM)akbarza Wrote: explain to me why Python acts as this.
This is explained in the documentation of super
Documentation Wrote:The search starts from the class right after the type.

For example, if __mro__ of object_or_type is D -> B -> C -> A -> object and the value of type is B, then super() searches C -> A -> object.
In your case, the __mro__ of g is grandchild -> child1 -> child2 -> parent -> object So in child1, super() finds child2 before parent.

hi, thanks for the reply
I think I read the segment of document about super() at least five
Reply
#5
hi
thanks for all your replies
I have read what you said in your replies.
as mentioned, this subject is discussed in the address in the docstring of the first thread.
In that address, the person after all explanations, has a question like this again: how and why does Python in line 22 (super().form1()) go to method form1 in class child2? I have read about MRO and know some about it. but still, i don't know why Python in line 22 goes to child2-form1 .
Reply
#6
(Feb-02-2024, 08:10 AM)akbarza Wrote: but still, i don't know why Python in line 22 goes to child2-form1 .
That's because you read the documentation but you don't understand it.

At line 22, python will run super(child1, self).form1() . It means that it will search and call method form1() in the part of the __mro__ of self that comes after child1. This part of the __mro__ is child2 -> parent -> object. As there is a method named form1() in child2, it is this method that gets called.
« We can solve any problem by introducing an extra level of indirection »
Reply
#7
(Feb-02-2024, 09:01 AM)Gribouillis Wrote:
(Feb-02-2024, 08:10 AM)akbarza Wrote: but still, i don't know why Python in line 22 goes to child2-form1 .
That's because you read the documentation but you don't understand it.

At line 22, python will run super(child1, self).form1() . It means that it will search and call method form1() in the part of the __mro__ of self that comes after child1. This part of the __mro__ is child2 -> parent -> object. As there is a method named form1() in child2, it is this method that gets called.

hi
in the code there is super().form1() . you said
Quote:At line 22, python will run super(child1, self).form1()
. how does Python recognize this argument for super() in that line?
Reply
#8
(Feb-04-2024, 06:28 AM)akbarza Wrote: how does Python recognize this argument for super() in that line?
It is a very good question. I don't know the complete answer however the documentation of super() gives this example (with this exact comment)
class C(B):
    def method(self, arg):
        super().method(arg)    # This does the same thing as:
                               # super(C, self).method(arg)
Furthermore, if you type help(super) in the Python console, it says
class super(object)
 |  super() -> same as super(__class__, <first argument>)
 |  super(type) -> unbound super object
 |  super(type, obj) -> bound super object; requires isinstance(obj, type)
 |  super(type, type2) -> bound super object; requires issubclass(type2, type)
...
this suggests that it uses a local hidden variable named __class__. This variable can indeed be accessed in a method
>>> class A:
...     def foo(self):
...         print(__class__)
... 
>>> A().foo()
<class '__main__.A'>
>>> 
Further investigation indicates that this variable is loaded from a place called 'fast locals storage'
>>> import dis
>>> dis.dis(A.foo)
  3           0 LOAD_GLOBAL              0 (print)
              2 LOAD_DEREF               0 (__class__)
              4 CALL_FUNCTION            1
              6 POP_TOP
              8 LOAD_CONST               0 (None)
             10 RETURN_VALUE
>>> 
Documentation Wrote:LOAD_DEREF(i)
Loads the cell contained in slot i of the “fast locals” storage. Pushes a reference to the object the cell contains on the stack.
akbarza likes this post
« We can solve any problem by introducing an extra level of indirection »
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Problems with super() Hoespilaar 2 270 Apr-10-2024, 10:10 AM
Last Post: Hoespilaar
  class definition and problem with a method HerrAyas 2 267 Apr-01-2024, 03:34 PM
Last Post: HerrAyas
  super() in class akbarza 1 472 Dec-19-2023, 12:55 PM
Last Post: menator01
  the order of running code in a decorator function akbarza 2 535 Nov-10-2023, 08:09 AM
Last Post: akbarza
  "Name is not defined" when running a class lil_e 6 4,054 Jan-12-2023, 11:57 PM
Last Post: lil_e
  Using one child class method in another child class garynewport 5 1,610 Jan-11-2023, 06:07 PM
Last Post: garynewport
  Child class inheritance issue eakanathan 3 1,353 Apr-21-2022, 12:03 PM
Last Post: deanhystad
  [Solved] Novice question to OOP: can a method of class A access attributes of class B BigMan 1 1,324 Mar-14-2022, 11:21 PM
Last Post: deanhystad
  class, attribute and method Frankduc 9 2,487 Feb-27-2022, 09:07 PM
Last Post: deanhystad
  Subclass initialized property used in parent class method. Is it bad coding practice? saavedra29 5 1,802 Feb-07-2022, 07:29 PM
Last Post: saavedra29

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020