文中代碼基於Python3.7
MRO規則可以總結為以下三句話:
-
In the multiple inheritance scenario, any specified attribute is searched first in the current class. If not found, the search continues into parent classes in depth-first, left-right fashion without searching the same class twice.
-
So, first it 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, which is a super class for all classes.
這里的list指的是多個父類組成的list,如:
class M(X,Y,Z):
pass
list就是(X,Y,Z)
-
When in MRO we have a super class before subclass then it must be removed from that position in 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。