Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

super confusing python multiple inheritance super()

I was playing around with the multiple inheritance in python and I come a cross a situation that I can't understand how it happen.

Here is the inheritance layout:

    A       F
  /   \     |
 B     C    |   
  \    |   /
    \  |  /   
       D

The ABCD diamond that everyone familiar with. Plus an extra class "F" I throw it in for fun.

Here is the code:

class A(object):
    def foo(self, call_from):
        print "foo from A, call from %s" % call_from
        super(A, self).foo("A")

class B(A):
    def foo(self, call_from):
        print "foo from B, call from %s" % call_from
        super(B, self).foo("B")

class C(A):
    def foo(self, call_from):
        print "foo from C, call from %s" % call_from
        super(C, self).foo("C")

class F(object):
    def foo(self, call_from):
        print "foo from F, call from %s" % call_from

class D(B, C, F):
    def foo(self):
        print "foo from D"
        super(D, self).foo("D")

output:

>>> d = D()
>>> d.foo()
foo from D
foo from B, call from D
foo from C, call from B
foo from A, call from C
foo from F, call from A

The method resolution order:

>>> D.__mro__
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class '__main__.F'>, <type 'object'>)
  • foo from C, call from B instead of foo from C, call from D
  • foo from F, call from A just simply throw me off...

It seems like the super() are chained up according to the method resolution order and ignore the relationship between classes, but I not sure.

Can someone point me to the right direction to understand this behavior?

Please keep in mind that I'm trying to understand the language itself. Not trying to solve a practical problem. So I don't have an use case for this. But it will be nice if someone can point out an use case :)


UPDATE:

To summarize - super() simply let you know what is next to call base on the mro. It is not necessary the parent. While mro built base on the inheritance hierarchy, mro itself is not the inheritance hierarchy.

like image 652
wilson Avatar asked Jul 06 '12 01:07

wilson


People also ask

Can we use super in multiple inheritance in Python?

Supercharge Your Classes With Python super()Python supports inheritance from multiple classes.

What is super () method in Python?

The super() function is used to give access to methods and properties of a parent or sibling class. The super() function returns an object that represents the parent class.

How do you use super in multilevel inheritance in Python?

Python super function with multilevel inheritance Well, Python super() will always refer the immediate superclass. Also Python super() function not only can refer the __init__() function but also can call all other function of the superclass. So, in the following example, we will see that.

What does super () __ Init__ do?

When you initialize a child class in Python, you can call the super(). __init__() method. This initializes the parent class object into the child class. In addition to this, you can add child-specific information to the child object as well.


1 Answers

The whole point of super() is to follow the method resolution order. That's why you tell it your own class, not your parent class. It's hard for the programmer to predict which class will be invoked next, so you let super() take care of it.

You already had B called from D, so how could you then get C called from D? D.foo() can only call one other foo(), because you only have one function call there. It's going to be a linear chain of calls, so the classes have to be linearized, that's what the method resolution order does.

like image 176
Ned Batchelder Avatar answered Nov 01 '22 03:11

Ned Batchelder