Solve the problem of python super of calling multiple inheritance functions

  • 2021-07-01 07:55:21
  • OfStack

When the inheritance relationship between classes is simple, the use of super () is simple.


class A(object):
 def __init__(self):
  print('a')
 
 
class B(A):
 def __init__(self):
  super(B, self).__init__()
  print('b')
 
b = B()

Output:


a
b

When one class inherits multiple classes, the problem is complicated. Please see the following example:


class A(object):
 def __init__(self):
  print('a')
 
 
class B(object):
 def __init__(self):
  print('b')
  
  
class C(A, B):
 def __init__(self):
  super(C, self).__init__()
  print('c')
 
c = C()

At first glance, the situation doesn't seem complicated. As a result, a and c are output. That's right! But what if the C class wants to call __init__ () of A and B at the same time?

There are children's shoes to say, I show that the call is not OK?


class A(object):
 def __init__(self):
  print('a')
 
 
class B(object):
 def __init__(self):
  print('b')
  
  
class C(A, B):
 def __init__(self):
  A.__init__()
  B.__init__()
  print('c')
 
c = C()

The effect is 1, which is not good enough. Because super () is not called, one of the great benefits of super is that when the name of the parent class is changed, its inherited class does not have to change the calling method.

Here's the perfect solution:


class A(object):
 def __init__(self):
  super(A, self).__init__()
  print('a')
 
 
class B(object):
 def __init__(self):
  super(B, self).__init__()
  print('b')
 
 
class C(A, B):
 def __init__(self):
  super(C, self).__init__()
  print('c')
 
print(C.mro())
c = C()

print (C. mro ()) can be removed in practice, so why write it here and talk about it later.

Output:


[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <type 'object'>]
b
a
c

Note: The output is b, a, c instead of a, b, c. Why?

This is explained by the mro () output above. The full name of MRO is Method Resolution Order, which is used to define the calling order of inheritance methods. Since Python 2.3, MRO has been defined by breadth-first (different from depth-first) rules. According to the breadth-first rule, the order of coming out is:


[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <type 'object'>]

Every time super () is called, the next function in MRO is called. In the above example: super (C, self) points to the next class (A) in MRO, and calls init of A-- > In init of A, super () is called again, so the next function in MRO (B) is called-- > B calls the next one (object), and object does nothing- > Returns in B, print ('b')-- > Returns print ('a') in A-- > Returns print ('c') in C.

Again, the super (type, obj). The func () function calls the callable func () of the next parent class of the obj instance in MRO, not func () of the parent class of type (this is an illusion given to you by the first example in this article).


Related articles: