在本教程中,我們將學習方法解析順序,也稱為 MRO。這是 Python 繼承的一個基本概念。
方法解析順序描述了類的搜索路徑 Python 使用該路徑在包含多重繼承的類中獲取合適的方法。
介紹
我們知道,被繼承的類稱為子類或父類,而繼承的類稱為子類或子類。在多重繼承中,一個類可以由許多函數組成,因此使用方法解析順序技術來搜索基類的執行順序。
簡而言之——「在當前類中探索方法或屬性,如果方法不在當前類中,則搜索移動到父類,依此類推」。這是深度優先搜索的一個例子。
它在多重繼承中起着重要的作用,在多重超類中可以找到相同的方法。
為了更好地理解它,讓我們看看如何使用它。
示例-
class A:
def myname(self):
print("I am a class A")
class B(A):
def myname(self):
print("I am a class B")
class C(A):
def myname(self):
print("I am a class C")
c = C()
print(c.myname())
輸出:
I am a class C
解釋-
上述代碼中存在多重繼承。我們定義了三個類,分別叫做 A,B,C,這些類有相同的名字方法叫做 myname()。我們創建了一個對象類 C,這個對象調用的是類 C,而不是類,而類 C 繼承了類 A 的方法。
上面代碼中遵循的順序是B 類->a 類。這種技術被稱為 MRO(方法解析順序)。
讓我們理解多重繼承的另一個例子。
示例-
class A:
def myname(self):
print(" I am a class A")
class B(A):
def myname(self):
print(" I am a class B")
class C(A):
def myname(self):
print("I am a class C")
# classes ordering
class D(B, C):
pass
d = D()
d.myname()
輸出:
I am a class B
解釋-
在上面的代碼中,我們創建了另一個 D 類,但沒有定義繼承 B 類和 C 類的類屬性。當我們調用方法 myname(),時,它會轉到 D 類並搜索 myname( )函數。但是 D 類沒有任何聲明。因此,搜索轉移到 B 類,得到 myname() 函數,並返回結果。搜索將按如下方式進行。
Class D -> Class B -> Class C -> Class A
如果 B 類沒有方法,它將調用 C 類方法。
在這裡,我們建議您刪除 B 類方法,並檢查發生了什麼。通過這樣做,您將了解方法解析是如何工作的。
新舊風格順序
在舊版 Python (2.1)中,我們被限制使用舊類,但是 Python (2.2 &繼續),我們可以使用新類。默認情況下,Python 3 有原始(新)類。新樣式類的第一個父類繼承自 Python 根「對象」類。讓我們看看下面的例子-
示例-
# Old style class
class OldStyleClass:
pass
# New style class
class NewStyleClass(object):
pass
兩個類的聲明風格不同。在方法解析中,舊樣式類遵循深度優先從左到右算法(DLR),而新樣式類在執行多重繼承時使用 C3 線性化算法。
動態鏈接庫算法
Python 創建了一個類列表,同時實現了類之間的多重繼承。該列表用於確定哪個方法必須被調用,哪個方法由實例調用。
我們可以假設按名稱工作,因為方法解析將首先搜索深度,然後從左到右。下面是例子。
示例-
class A:
pass
class B:
pass
class C(A, B):
pass
class D(B, A):
pass
class E(C,D):
pass
首先,算法將在實例類中搜索被調用的方法。如果沒有找到,它就進入第一個父母,如果有也沒有找到。它將查看父代的父代。這將持續到繼承類結束。
在上面的示例中,方法解析順序將是-
class D -> class B -> class A -> class C -> class A
但是,A 不能出現兩次,所以-
class D -> class B -> class A -> class C ->
這個算法顯示了當時的奇怪行為。讓我們看看下面的例子。
示例-
class A:
pass
class B:
pass
class C(A, B):
pass
class D(B, A):
pass
class E(C,D):
pass
根據 DLR 算法,順序會是 E,C,D,B,a,C 類中有 A & B 類的互換,很曖昧。這意味着算法沒有保持單調性。
塞繆爾·佩多尼是第一個發現 MRO 算法之間不一致的人。
C3 線性化算法
C3 線性化算法是 DLR 算法的更好版本,因為它消除了不一致性。該算法有一些限制,如下所示。
- 孩子必須先於父母。
- 如果一個特定的類從一個或多個類繼承,它們將按照基類元組中指定的順序保存。
C3 線性化算法的規則
- 方法解析順序的結構由繼承圖定義。
- 只有在訪問了本地類的方法之後,用戶才能訪問超級類。
- 保持單調性
方法解析類的方法
Python 提供了兩種方法來獲取類的方法解析順序- mro 屬性或 mro() 方法。在這些方法的幫助下,我們可以顯示它們被解析的方法順序。
讓我們理解下面的例子。
示例-
class A:
def myname(self):
print(" I am a class A")
class B(A):
def myname(self):
print(" I am a class B")
class C(A):
def myname(self):
print("I am a class C")
# classes ordering
class D(B, C):
pass
# it prints the lookup order
print(D.__mro__)
print(C.mro())
輸出:
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
[<class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
正如我們在上面的輸出中看到的,我們得到了方法解析順序的順序。這樣,C3 線性化算法適用於多重繼承。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/300962.html