Python 中的兄弟姐妹 class 是什么?

What is a sibling class in Python?

Python 2 文档说 super() 函数 "returns a proxy object that delegates method calls to a parent or sibling class of type."

问题:

  1. Python 中的兄弟 class 是什么?
  2. 如何将方法调用委托给兄弟 class?

我的假设是给定 class 的兄弟姐妹是从同一个 parent 继承的 class。我起草了以下代码以查看如何将方法调用委托给兄弟姐妹,但它没有用。我是怎么做的还是理解错了?

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'

兄弟姐妹是 class 与您所怀疑的相同 parent。你遗漏的情况是 super 可以调用兄弟方法 如果这个 class 本身是从 :

多重继承的
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——这是一个兄弟,不是一个parent 和 不是 兄弟姐妹的 parent,而是 C 的直接兄弟姐妹。

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

  1. 兄弟姐妹 class 是我所想的。它是继承自同一个 parent 的 class。 Python 文档的定义让我偏离了课程。似乎当 Python 文档说 将方法调用委托给 parent 或同级 class 时,这意味着 给 parent 或 parent 的兄弟,它也是给定 child 的基础 class。那是钻石继承必须发生的。

  2. super() 函数根据 MRO (方法解析顺序)。

这是我在试验 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

如果你和我一样想知道为什么 MethodA of Class0 从未被打印出来,这里是我理解的解释。用 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 链。