Python MRO


文中代碼基於Python3.7

 

對於Python中的多繼承情況,運行時在搜索對象的屬性或方法時,需要遵循一定的順序規則,這個規則稱為:Method Resolution Order (MRO).

 

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): 
    passprint(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): 
    passprint(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): 
    passprint(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):
    passprint(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。

推薦閱讀

Python Multiple Inheritance

Method Resolution Order (MRO) in Python


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM