方法解析顺序 (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()
。请解释为什么会这样?
documentation 对 super()
的工作原理有很好的解释:
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.
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()
。请解释为什么会这样?
documentation 对 super()
的工作原理有很好的解释:
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__
ofobject-or-type
isD -> B -> C -> A -> object
and the value of type isB
, thensuper()
searchesC -> 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.