超级混乱的python多重继承 super()

Posted

技术标签:

【中文标题】超级混乱的python多重继承 super()【英文标题】:super confusing python multiple inheritance super() 【发布时间】:2012-07-06 11:23:36 【问题描述】:

我正在玩 python 中的多重继承,但遇到了一个我无法理解它是如何发生的情况。

继承布局如下:

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

大家都熟悉的ABCD钻石。 加上一个额外的“F”类,我把它扔进去是为了好玩。

代码如下:

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")

输出:

>>> 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

方法解析顺序:

>>> 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 而不是 foo from C, call from D foo from F, call from A 干脆把我赶走...

好像super()是按照方法解析顺序串起来的,忽略了类之间的关系,但我不确定。

有人可以指出正确的方向来理解这种行为吗?

请记住,我正在尝试理解语言本身。不试图解决实际问题。所以我没有这个用例。但是如果有人能指出一个用例那就太好了:)


更新:

总结一下 - super() 只是让您知道接下来要调用的基于 mro 的内容。不需要父母。虽然 mro 基于继承层次结构构建,但 mro 本身并不是继承层次结构。

【问题讨论】:

阅读 Python MRO 模型的故事 你期待什么输出? 【参考方案1】:

super() 的全部意义在于遵循方法解析顺序。这就是为什么你告诉它你自己的班级,而不是你的父母班级。程序员很难预测接下来会调用哪个类,所以你让super() 来处理它。

你已经从 D 调用了 B,那么你怎么能从 D 调用 C? D.foo() 只能调用另一个 foo(),因为那里只有一个函数调用。这将是一个线性的调用链,因此必须对类进行线性化,这就是方法解析顺序的作用。

【讨论】:

【参考方案2】:

有时我发现在父类上调用 super 很有用。例如。

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

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

现在我想从 TmpClass2 的实例中使用 TmpClass0 的 tmp_method。

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

结果:

In [107]: tmp_class2 = TmpClass2()                                                                                  

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

【讨论】:

以上是关于超级混乱的python多重继承 super()的主要内容,如果未能解决你的问题,请参考以下文章

python super()函数的用法与多重继承

Python 的 super() 如何与多重继承一起工作?

Python多重继承引发的问题——牛逼的super

python中的多重继承与超级[重复]

Python入门-6面向对象编程:08多重继承-mro()-super()获得父类的定义

具有多重继承的 Python super().__init__()