什么是Python中的兄弟类?

时间:2015-01-14 23:59:20

标签: python oop inheritance super siblings

Python 2文档说super()函数“返回一个代理对象,它将方法调用委托给父类或兄弟类类型。”

问题:

  1. Python中的兄弟类是什么?
  2. 如何将方法调用委托给兄弟类?
  3. 我的假设是,给定类的兄弟是一个继承自同一父母的类。我起草了以下代码,以了解如何将方法调用委托给兄弟,但它不起作用。我该怎么做或理解错了?

    class ClassA(object):
        def MethodA(self):
            print "MethodA of ClassA"
    
    class ClassB(ClassA):
        def MethodB(self):
            print "MethodB of ClassB"
    
    class ClassC(ClassA):
        def MethodA(self):
            super(ClassC, self).MethodA()
    
        def MethodB(self):
            super(ClassC, self).MethodB()
    
    if __name__ == '__main__':
        ClassC().MethodA() # Works as expected
    
        # Fail while trying to delegate method to a sibling.
        ClassC().MethodB() # AttirbuteError: 'super' object has no attribute 'MethodB'
    

2 个答案:

答案 0 :(得分:7)

经过一些进一步的研究和阅读Python’s super() considered super!文章后,我得出了以下结论:

  1. 兄弟姐妹课就是我的想法。它是一个继承自同一父级的类。正是Python文档的定义让我不再参与其中。似乎当Python文档说委托对父或兄弟类的方法调用时,它意味着给父母或父母的兄弟,这也是给定孩子的基类。这是钻石继承必须发生的。

  2. super()函数根据MRO(方法解析顺序)自动委托对父级兄弟类的方法调用。

  3. 这是我在尝试使用super()函数时发现的一个有趣案例:

    class Class0(object):
        def MethodA(self):
            print("MethodA of Class0")
    
    class ClassA(Class0):
        def MethodA(self):
            super(ClassA, self).MethodA()
            print("MethodA of ClassA")
    
    class ClassB(Class0):
        def MethodA(self):
            print("MethodA of ClassB")
    
    class ClassC(ClassA, ClassB):
        def MethodA(self):
            super(ClassC, self).MethodA()
    
    if __name__ == '__main__':
        ClassC().MethodA()
    

    代码将打印

    MethodA of ClassB
    MethodA of ClassA
    

    如果你像我一样想知道为什么 Class0 的MethodA永远不会被打印出来,这就是我理解的解释。使用print(ClassC.__mro__)打印的ClassC的MRO是

    (<class '__main__.ClassC'>, <class '__main__.ClassA'>, <class '__main__.ClassB'>, <class '__main__.Class0'>, <class 'object'>)

    现在,如果您按照MRO,ClassC的MethodA()的super()函数将调用ClassA的MethodA(),在打印之前将调用classB的MethodA()(因为它是MRO中的下一个)。而且,ClassB的MethodA()只会打印并退出,因为它不使用super()函数将方法调用委托给MRO链进一步调整。

答案 1 :(得分:1)

兄弟姐妹是一个与您怀疑的父母相同的班级。你遗漏的情况是super可以调用兄弟方法如果这个类本身是从中多次继承的话:

class A(object):
  def something(self):
    print("A")
class B(A):
  def something(self):
    print("B")
class C(A):
  def something(self):
    print("C, about to call super()")
    super(C, self).something()
class D(C, B):
  def something(self):
    super(D, self).something()

>>> D().something()
C, about to call super()
B

C,我们调用了super(),但我们得到了B - 这是一个兄弟,不是父母而不是兄弟姐妹的父母,但C的实际直接兄弟。