CodeGym /Java Adesua /Python SELF TW /方法解析順序 (MRO)

方法解析順序 (MRO)

Python SELF TW
等級 16 , 課堂 5
開放

11.1 方法解析順序

方法解析順序 (Method Resolution Order, MRO) 決定了 Python 在類層次結構中搜索方法和屬性的順序。這在使用多重 繼承時尤其重要,因為類可能從多個父類繼承屬性和方法。

簡單來說,有一個固定的順序(或更確切地說,是算法), 根據這個順序 Python 瀏覽類的繼承樹。這個算法 保證了方法搜索的正確順序,可以描述為:

C3線性化算法

C3線性化算法通過組合以下方式來確定MRO:

  • 類本身。
  • 按照它們被列舉的順序的父類清單。
  • 以相同順序的父類的MRO

C3線性化算法規則

  • 保持方法的局部順序: 如果類 A 在類 B 之前列出,那麼類 A 的所有方法都應該在 類 B 的方法之前考慮。
  • 保持父類的順序: 如果類 A 是類 B 的父類,那麼類 A 的所有方法都應該 在類 B 的方法之前考慮。
  • 考慮繼承順序: 如果類 C 是 兩個或多個類的父類,那麼類 C 方法的順序應該在所有這些類的MRO中保持。

算法步驟:

步驟 1. 從類本身開始:

總是從調用方法的類本身開始。

步驟 2. 按照列舉順序添加基類:

在當前類之後,按照繼承時指定的順序檢查其基類。

步驟 3. 瀏覽父類:

那裡查找字段和方法。

步驟 4. 合併父類的MRO:

如果同一個基類通過多個路徑繼承,它 只被檢查一次並且按正確的順序(其餘時間都將被忽略)。

對於已經了解“算法和數據結構”主題的人來說,這 是深度優先搜索,而不是廣度優先搜索。

11.2 檢查MRO

在 Python 中,可以使用屬性 __mro__ 或函數 mro() 檢查類的字段和方法的搜索順序。

範例:


class A:
    def method(self):
        print("A")
        
class B(A):
    def method(self):
        print("B")
        
class C(A):
    def method(self):
        print("C")
        
class D(B, C):
    def method(self):
        print("D")
        

# 檢查 MRO
print(D.__mro__)
        

輸出將是:


(<class '__main__.D'>, 
<class '__main__.B'>, 
<class '__main__.C'>,
<class '__main__.A'>,
<class 'object'>)
        

這顯示了 Python 將如何搜索方法和屬性的順序:

  • D: Python 首先檢查類 D 中的方法。
  • B: 然後 Python 檢查類 B 中的方法(第一個 父類)。
  • C: 如果在類 B 中找不到方法,Python 檢查 類 C 中的方法(第二個父類)。
  • A: 如果在類 BC 中找不到方法,Python 檢查類 A 中的方法。
  • object: 最後,Python 檢查 基礎類 object 中的方法。

11.3 使用 super() 和 MRO

函數 super() 遵循 MRO 來正確順序呼叫 父類的方法。考慮以下 super() 的使用範例:

class A:
    def method(self):
        print("A")
        super().method()
        
class B(A):
    def method(self):
        print("B")
        super().method()
        
class C(A):
    def method(self):
        print("C")
        super().method()
        
class D(B, C):
    def method(self):
        print("D")
        super().method()
        
        
d = D()
d.method()
        

輸出將如下:


D
B
C
A
        

搜索順序 (MRO)

1. 調用類 Dmethod 方法:

  • Python 首先檢查類 D 並在那裡找到方法。
  • 方法 D.method() 執行並打印 "D"
  • 然後調用 super().method(),它遵循 MRO 來調用 下一個方法。

2. 調用類 Bmethod 方法:

  • 根據 MRO,D 之後的類是 B
  • 方法 B.method() 執行並打印 "B"
  • 然後調用 super().method(),它遵循 MRO 來調用 下一個方法。

3. 調用類 Cmethod 方法:

  • MRO 中 B 之後的類是 C
  • 方法 C.method() 執行並打印 "C"
  • 然後調用 super().method(),它遵循 MRO 來調用 下一個方法。

4. 調用類 Amethod 方法:

  • MRO 中 C 之後的類是 A
  • 方法 A.method() 執行並打印 "A"
  • 然後調用 super().method(),但因為 A 沒有其他 父類方法 method(除了 object),所以調用結束。
1
Опрос
繼承,  16 уровень,  5 лекция
недоступен
繼承
繼承
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION