super confusing python multiple inheritance super()

坚强是说给别人听的谎言 提交于 2019-11-30 15:11:10

问题


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.


回答1:


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.




回答2:


Occasionally I find it useful to call super on parent class. Ex.

class TmpClass0(object):
    def tmp_method(self):
        print 'TmpClass0 tmp_method'

class TmpClass1(TmpClass0):
    def tmp_method(self):
        print 'TmpClass1 tmp_method'

Now I want to use TmpClass0's tmp_method from an instance of TmpClass2.

class TmpClass2(TmpClass1):                                                                               
    def tmp_method(self):
        super(TmpClass1, self).tmp_method()

Result:

In [107]: tmp_class2 = TmpClass2()                                                                                  

In [108]: tmp_class2.tmp_method()                                                                                   
TmpClass0 tmp_method


来源:https://stackoverflow.com/questions/11354786/super-confusing-python-multiple-inheritance-super

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!