文中代码基于Python3.7
对于Python中的多继承情况,运行时在搜索对象的属性或方法时,需要遵循一定的顺序规则,这个规则称为:Method Resolution Order (MRO).
MRO规则可以总结为以下三句话:
可以调用类型对象的mro
方法或者__mro__
属性来获取类型的MRO信息。
class X:
def hello(self):
print('x')
class Y:
def hello(self):
print('y')
def world(self):
print('y_world')
class Z:
def hello(self):
print('z')
class A(X):
def hello(self):
print('a')
class B(Y,Z):
def hello(self):
print('b')
class M(B, A):
pass
print(M.mro())
print(M.__mro__)
# 输出:
# list类型
[<class '__main__.M'>, <class '__main__.B'>, <class '__main__.Y'>, <class '__main__.Z'>, <class '__main__.A'>, <class '__main__.X'>, <class 'object'>]
# tuple类型
(<class '__main__.M'>, <class '__main__.B'>, <class '__main__.Y'>, <class '__main__.Z'>, <class '__main__.A'>, <class '__main__.X'>, <class 'object'>)
MRO图示如下:
goes to super class (and its super classes) given first in the list then second super class (and its super classes) , from left to right order. Then finally Object class
depth-first, left-right fashion without searching the same class twice ,得到MRO列表:[<class '__main__.M'>, <class '__main__.B'>, <class '__main__.Y'>, <class '__main__.Z'>, <class '__main__.A'>, <class '__main__.X'>, <class 'object'>]
B和A均继承自Z,M继承自B和A:
class X:
def hello(self):
print('x')
class Y:
def hello(self):
print('y')
def world(self):
print('y_world')
class Z:
def hello(self):
print('z')
class A(X,Z):
def hello(self):
print('a')
class B(Y,Z):
def hello(self):
print('b')
class M(B, A):
pass
print(M.mro())
# 输出:
# [<class '__main__.M'>, <class '__main__.B'>, <class '__main__.Y'>, <class '__main__.A'>, <class '__main__.X'>, <class '__main__.Z'>, <class 'object'>]
MRO图示如下:
goes to super class (and its super classes) given first in the list then second super class (and its super classes) , from left to right order. Then finally Object class
depth-first, left-right fashion without searching the same class twice ,得到MRO列表:[<class '__main__.M'>, <class '__main__.B'>, <class '__main__.Y'>, <class '__main__.A'>, <class '__main__.X'>, <class '__main__.Z'>, <class 'object'>]
class X:
def hello(self):
print('x')
class Y:
def hello(self):
print('y')
def world(self):
print('y_world')
class Z:
def hello(self):
print('z')
class A(X,Z):
def hello(self):
print('a')
class B(Y,Z):
def hello(self):
print('b')
class M(B, A, Y):
pass
print(M.mro())
# 输出
# [<class '__main__.M'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.Y'>, <class '__main__.X'>, <class '__main__.Z'>, <class 'object'>]
MRO图示如下:
goes to super class (and its super classes) given first in the list then second super class (and its super classes) , from left to right order. Then finally Object class
这个MRO图可以继续简化:
depth-first, left-right fashion without searching the same class twice
得到MRO列表为[<class '__main__.M'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.Y'>, <class '__main__.X'>, <class '__main__.Z'>, <class 'object'>]
When in MRO we have a super class before subclass then it must be removed from that position in MRO
下面是一个会报错的示例:
class A:
def process(self):
print('A process()')
class B(A):
def process(self):
print('B process()')
class M(A, B):
pass
print(M.mro())
# 输出:
# TypeError: Cannot create a consistent method resolution
# order (MRO) for bases A, B
MRO图示:
如果一个方法或属性同时存在与B和A,应为M直接继承B又直接继承A,那么通过M来调用时就不知道是该从B中还是A中获取这个方法或属性了,干脆就报错吧。我觉得MRO顺序应该为:M->B->A->object。