MRO
MRO即method resolution order,方法调用顺序。python是一门支持多继承的语言,当一个子类(该子类继承了两个父类)的对象执行方法A时,该子类没有定义方法A,而两个父类都定义了方法A,那么应该执行哪个父类的方法A?这个时候就需要MRO来制定执行顺序。
看个例子
class F():
pass
class A(F):
pass
class B(F):
pass
class C(A, B):
pass
print(C.mro())
输出结果
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.F'>, <class 'object'>]
MRO的计算过程
使用O记号来表示某个类的MRO,假如类M的父类为[M1, M2…Mn],
O(M) = [M] + [O(M1), O(M2)…O(Mn), [M1], [M2]…[Mn]]
加号之后是一串列表,其中每个列表的第一个元素为该列表头,列表中的剩余元素为该列表的尾。从一串列表中的最左边开始,取该列表的头,假如该列表的头没有出现在其他列表的尾中,那么就可以把这个头提到列表外,作为次一级优先级的类与之前的合并。同时把该类从所有的列表中删除。一直持续到列表为空。如果最后列表不为空,说明这是个错误的继承,python中会给出异常提示。
还是上边的例子
O(F) = [F]
O(A) = [A] + [O(F)] = [A] + [F] = [A, F]
O(B) = [B] + [O(F)] = [B] + [F] = [B, F]
O[C] = [C] + [O(A), O(B), [A], [B] ]
= [C] + [[A, F], [B, F], [A], [B] ]
= [C, A] + [[F], [B, F], [B] ]
= [C,A,B] + [[F], [F] ]
= [C, A, B, F]
当C的实例调用某个方法时,就按照该顺序进行查找,直到找到实现了该方法的类。
class F():
def foo(self):
print('i am f fool')
class A(F):
pass
class B(F):
def foo(self):
print('i am b fool')
class C(A, B):
pass
C().foo()
输出结果
i am b fool
在沿着MRO查找的过程中,C和A都没有实现该方法,查找到B的时候,发现B实现了该方法,就执行了B的foo方法。
class F():
def foo(self):
print('i am f fool')
class A(F):
def foo(self):
print('i am a fool')
super(A, self).foo()
class B(F):
def foo(self):
print('i am b fool')
class C(A, B):
pass
C().foo()
执行结果
i am a fool
i am b fool
在查找foo的方法的过程中,发现A实现了该方法,打印了 i am a fool,由于A的foo方法调用的父类的foo方法,在MRO中可以看到A之后的类为B,于是下一步再执行B类中实现的foo方法。