首页 文章

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

提问于
浏览
8

我正在玩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本身并不是继承层次结构 .

2 回答

  • 7

    super() 的重点是遵循方法解析顺序 . 那个程序员很难预测接下来会调用哪个类,所以你让 super() 来处理它 .

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

  • 1

    偶尔我发现在父类上调用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
    

相关问题