【问题标题】:python diamond inheritance and the use of super() in the parents of the derived classpython菱形继承以及派生类的父类中super()的使用
【发布时间】:2012-04-05 18:44:52
【问题描述】:

首先,我必须为没有更好的标题而道歉。如果您找到更合适的,请随时更改。

基本上,我一直被 Python 的多重继承行为所困扰。在我的previous SO question 中,我被指示阅读Python's C3 MRO。这确实有助于我更好地理解 Python 中的多重继承。就在我以为我掌握了它的时候,我碰到了以下场景,我似乎无法理解。

class UltimateBase(object):
    def check(self):
        print 'base check'

class AMixin1(UltimateBase):
    def check(self):
        print 'check A'

class BMixin1(UltimateBase):
    def check(self):
        print 'check B'

class CMixin1(UltimateBase):
    def check(self):
        print 'check C'

class AMixin2(UltimateBase):
    def check(self):
        print 'check A'
        return super(AMixin2, self).check()

class BMixin2(UltimateBase):
    def check(self):
        print 'check B'
        return super(BMixin2, self).check()

class CMixin2(UltimateBase):
    def check(self):
        print 'check C'
        return super(CMixin2, self).check()

class MyView1(AMixin1, BMixin1, CMixin1):
    pass

class MyView2(AMixin2, BMixin2, CMixin2):
    pass

class MyView3(AMixin1, BMixin2, CMixin2):
    pass

class MyView4(AMixin2, BMixin1, CMixin2):
    pass

class MyView5(AMixin2, BMixin2, CMixin1):
    pass

class MyView6(AMixin1, BMixin1, CMixin2):
    pass

class MyView7(AMixin1, BMixin2, CMixin1):
    pass

class MyView8(AMixin2, BMixin1, CMixin1):
    pass

myview1 = MyView1()
myview2 = MyView2()
myview3 = MyView3()
myview4 = MyView4()
myview5 = MyView5()
myview6 = MyView6()
myview7 = MyView7()
myview8 = MyView8()

myview1.check()
print '------------------------'
myview2.check()
print '------------------------'
myview3.check()
print '------------------------'
myview4.check()
print '------------------------'
myview5.check()
print '------------------------'
myview6.check()
print '------------------------'
myview7.check()
print '------------------------'
myview8.check()
print '------------------------'

输出:

check A
------------------------
check A
check B
check C
base check
------------------------
check A
------------------------
check A
check B
------------------------
check A
check B
check C
------------------------
check A
------------------------
check A
------------------------
check A
check B
------------------------

我可以根据观察输出来追踪模式,但它让我不理解这个结果背后的基本原理。

我有一些问题,例如,为什么myview2.check() 会返回

check A
check B
check C
base check

不是

check A
base check

在我看来,我错过了关于多重继承的关键部分。请帮我填空。

【问题讨论】:

    标签: python python-2.7 multiple-inheritance


    【解决方案1】:

    当你调用myview2.check() 时,它会遍历兄弟姐妹然后调用基类。每当其中一个遍历命中 AMixin1BMixin1CMixin1 时,它就会停止,因为这些类不调用 super(..., self).check()

    正如 Benn 所指出的,这在 official Python documentation 中有所描述。如果你仔细想想,它几乎必须以这种方式工作。子类将假定在子类调用super() 之前未调用基类方法。如果是(或者,更糟糕的是,如果它取决于列出其兄弟姐妹的顺序),这会使事情变得非常难以处理。

    【讨论】:

    • 谢谢克里斯。这是相当违反直觉的。从结果来看,除非所有父母都调用super(),否则不会调用共同祖先的check()。有没有关于这方面的文献?
    • 我不会添加另一个大致相同的答案,而只是链接super() 的文档,在这种情况下它正在发挥作用:Official Python Docs。关键是它会调用type 的父母或兄弟姐妹来进行协作多重继承。
    • @Benn - 这正是我解决问题所需的最后一块。非常感谢。
    【解决方案2】:

    试图让我的头脑围绕同一个问题。 我发现以下代码有助于简化问题:

    (基本上,当一个类的所有supers 都被命中时,该类就会被调用。)

    class A:
      def f(self):
        print("............A: the common base of B and C")
    
    class B(A):
      def f(self):
        print("........B: the left base of D")
        super().f()
    
    class C(A):
      def f(self):
        print("........C: the right base of D")
        super().f()
    
    class D(B,C):
      def f(self):
        print("....D: the top class")
        super().f()
    
    d = D()
    
    d.f()
    

    输出:

    ....D: the top class
    ........B: the left base of D
    ........C: the right base of D
    ............A: the common base of B and C
    

    Try Online

    【讨论】:

      猜你喜欢
      • 2011-07-27
      • 1970-01-01
      • 1970-01-01
      • 2012-12-10
      • 1970-01-01
      • 2017-10-24
      • 1970-01-01
      • 1970-01-01
      • 2020-10-20
      相关资源
      最近更新 更多