方法解析顺序 (MRO) 如何在此 Python 代码中工作

How Method Resolution Order (MRO) is working in this Python code

class parent:
    def __init__(self):
        self.a=2
        self.b=4
    def form1(self): 
        print("calling parent from1")
        print('p',self.a+self.b)
 
class child1(parent):
    def __init__(self):
        self.a=50
        self.b=4
    def form1(self):
        print('bye',self.a-self.b)
    def callchildform1(self):
        print("calling parent from child1")
        super().form1()
 
class child2(parent):
    def __init__(self):
        self.a=3
        self.b=4
    def form1(self):
        print('hi',self.a*self.b)
    def callchildform1(self):
        print("calling parent from child2")
        super().form1()
 
class grandchild(child1,child2):
    def __init__(self):
        self.a=10
        self.b=4
    def callingparent(self):
        super().form1()
 
g=grandchild()
g.callchildform1()

在上面的代码中,当我调用g.callchildform1()时,根据MRO规则,该方法将首先在相同的class中搜索,然后是第一个parent(此处为child1 ) 然后是第二个 parent (child2)。 正如预期的那样,它调用 child1.callchildform1() 并执行第一行 print("calling parent from child1")。但在此之后,我预计下一行 super().form1() 将被执行,这将调用 parent.form1() 但这并没有发生。相反,正在调用 child2.form1()。请解释为什么会这样?

documentationsuper() 的工作原理有很好的解释:

super([type[, object-or-type]])

Return a proxy object that delegates method calls to a parent or sibling class of type. This is useful for accessing inherited methods that have been overridden in a class.

The object-or-type determines the method resolution order to be searched. The search starts from the class right after the type.

For example, if __mro__ of object-or-type is D -> B -> C -> A -> object and the value of type is B, then super() searches C -> A -> object.

super() 等同于表达式 super(__class__, self),其中 __class__ 是一个 class 对象,在其方法中调用了 super()。例如,grandchild.callingparent(self) 中的 super() 本质上是 super(grandchild, self)child1.callchildform1(self) 函数中的 super()super(child1, self).

MRO 对于 grandchild(<grandchild>, <child1>, <child2>, <parent>, <object>)。因此,根据上述文档摘录,在child1.callchildform1()中调用super().form1()时,相当于super(child1, self),搜索form1方法MRO 序列中 child1 之后的 class 开始,第一个匹配 class 与 form1 方法是 child2.

发生这种情况是因为您正在使用菱形继承结构和作为 MRO 基础的 principles

with multiple inheritance hierarchies, the construction of the linearization is more cumbersome, since it is more difficult to construct a linearization that respects local precedence ordering and monotonicity.

在设计这样的层次结构时,需要遵循协同继承的方法,可以找到解释,在这已经classic article.