【问题标题】:What is a sibling class in Python?Python中的兄弟类是什么?
【发布时间】:2015-03-13 07:55:52
【问题描述】:

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

问题:

  1. 什么是 Python 中的同级类?
  2. 如何将方法调用委托给同级类?

我的假设是给定类的兄弟是从同一个父类继承的类。我起草了以下代码来查看如何将方法调用委托给兄弟,但它不起作用。我做错了什么或理解错了?

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'

【问题讨论】:

  • 我没有时间写一个完整的答案,但我认为文档指的是多重继承。如果类 C 继承自 A 和 B,那么您可以认为 A 和 B 在某种意义上是“兄弟姐妹”。 super() 在 A 的主体中调用 C 的实例将委托给 B。请参阅 this question 了解详情。
  • 这里接受的这个问题的答案解释了super() 确实可以调用父类以及兄弟类的详细信息:stackoverflow.com/questions/5033903/…
  • @SimeonVisser,我已经看到了这个问题,甚至给它加了星标。它没有对兄弟类是什么给出明确的答案。这个问题与那个问题有关,但显然不是重复的。
  • @golem: 好吧,在那个例子中你可以看到super()调用兄弟类而不是父类的情况(BC都是A的子类) .同级类确实意味着您认为的含义:两个具有相同父类的类,因此它们是同级。 super() 可以调用父类以及兄弟类。希望这会有所帮助 - 如果没有,请告诉我。
  • @SimeonVisser,请取消将问题标记为重复,以便我可以将我的答案从问题正文移到答案。谢谢。

标签: python oop inheritance super siblings


【解决方案1】:

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

  1. 我认为是同级类。它是从同一个父类继承的类。正是 Python 文档的定义让我偏离了课程。似乎当 Python 文档说将方法调用委托给父类或兄弟类时,它意味着委托给父类或父类的兄弟,它们也是给定子类的基类。那是必须进行钻石继承。

  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 链的更上游。

【讨论】:

  • 所以ClassAClassB 被认为是“兄弟”类,因为它们都继承自Class0?我无法理解为什么在打印 MRO 时 ClassB 出现在 ClassA 之后。
  • 我对这个 MRO 感到非常困惑,因为 Classes 的 Python 文档说 MRO 是“深度优先,从左到右”——这意味着应该首先打印“Class0 的 MethodA”。事实证明,Python 有另一个规则,基本上说,如果 MRO 中稍后有 Class0 的后代可以解析调用,则不能选择祖先类(例如 Class0)来解析方法调用。这称为“好头”规则,确保方法的最具体(重新)定义优先。
【解决方案2】:

正如您所怀疑的,兄弟姐妹是具有相同父级的类。您缺少的情况是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 的直接兄弟。

【讨论】:

  • 谢谢,我也得出了同样的结论。我认为更精确的定义是 父母的兄弟姐妹,它也是给定孩子的基类 - 我在自己的答案中使用的定义。
  • 不,这不是一个准确的定义。 B 不是C父母的兄弟姐妹。它是C兄弟
  • B 是第一个父母,C 是第二个父母。 B 和 C 是兄弟姐妹。在 parent 的兄弟姐妹中,它也是给定子节点的基类,您将得到:B 的兄弟姐妹,也是 D 的基类。即 C =)。
  • B 不是C 中的父级,这就是调用super 并获得B 的原因。
猜你喜欢
  • 1970-01-01
  • 2014-03-29
  • 1970-01-01
  • 1970-01-01
  • 2015-08-28
  • 2017-08-12
  • 1970-01-01
  • 2012-08-02
  • 2021-09-22
相关资源
最近更新 更多