Contents

在 Python 類別中使用 super() 函數

要點

Python 使用 super() 函數可以透過存取其超類別來方便地呼叫子類別中的方法,從而以優雅的方式增強了實現繼承和方法重寫的過程。

super() 函數與 Python 中的方法解析順序 (MRO) 有著重要的聯繫,它控制在方法解析期間仔細檢查祖先類別的方法和屬性的順序。

在類別的建構子中使用 super() 是在父類別中建立共享特徵,同時在從屬類別中定義更多特定特徵的慣用方法。未能實現“ super() ”可能會導致不期望的結果,包括省略屬性初始化。

Python 程式語言的基本面向之一是其物件導向程式設計 (OOP) 範例,它允許創建以結構化方式表示現實生活中的物件及其互連的模型。

在使用 Python 程式設計的上下文中,通常使用繼承來修改或取代類別的父實體的特徵或功能。該語言提供了一種稱為“super()”函數的便捷機制,它允許從從屬類別中呼叫上級類別的方法。

什麼是 super() 以及為什麼需要它?

從現有類別繼承允許透過繼承過程建立具有相似屬性和行為的新類別。此外,人們可以選擇重寫子類別中的特定方法以提供自己獨特的實作。雖然這種新功能可能是理想的,但在某些情況下,最好同時使用原始功能和新實現的功能。在這種情況下,使用 super() 函數可以將兩組功能​​整合到子類別中。

為了在物件導向程式設計中利用超類別的屬性和方法,可以使用“super()”函數。該函數起著至關重要的作用,因為它有助於實現繼承和方法重寫,這是物件導向程式設計中的基本概念。

super() 是如何運作的?

在內部, super() 函數的行為與方法解析順序 (MRO) 的概念交織在一起,這是由 Python 中的 C3 線性化演算法確定的機制。

super() 的工作原理如下:

當在 Python 中的子類別的方法中呼叫 super() 時,語言會自動識別包含呼叫方法的當前類別以及由 self 表示的所述類別的實例。

⭐ 確定超類別: super() 有兩個參數-目前類別和實例-你不需要明確地通過。它使用此資訊來確定委託方法呼叫的超類別。它透過檢查類別層次結構和 MRO 來實現這一點。

一旦確定了超類,“super()”函數就允許呼叫其方法,就像直接從子類呼叫它們一樣。此功能有利於擴展和重寫超類別的方法,同時利用超類別提供的原始實作。

在類別建構子中使用 super()

在類別的建構子中結合使用 super() 方法是一種流行的方法,因為它可以初始化同級類別之間的共享屬性,同時允許每個單獨的後代具有獨特的特徵。

為了說明使用 Python 進行物件導向程式設計中繼承的概念,我們可以建立一個「Father」類,作為另一個名為「Son」的類別的基底類別。 「Son」類別將從其父類別「Father」繼承屬性和方法,從而示範繼承如何允許程式碼重複使用和模組化。

 class Father:
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

class Son(Father):
    def __init__(self, first_name, last_name, age, hobby):
        # Call the parent class constructor (Father)
        super().__init__(first_name, last_name)

        self.age = age
        self.hobby = hobby

    def get_info(self):
        return f"Son's Name: {self.first_name} {self.last_name}, \
Son's Age: {self.age}, Son's Hobby: {self.hobby}"

# Create an instance of the Son class
son = Son("Pius", "Effiong", 25, "Playing Guitar")

# Access attributes
print(son.get_info())

在「Son」類別的建構子的範圍內,呼叫其父類別的命令是透過呼叫「super()」函數的驚人行為來執行的。這個關鍵動作觸發了父類別 Father 類別建構子的啟動,以 first\_namelast\_name 變數的形式提供了兩個受人尊敬的最重要限定符。以這種方式,「父親」類別保留了準確地獲得和分配這些名義名稱的能力,儘管實例化了「兒子」。

/bc/images/using-super-in-class-constructor.jpg

在構造中未呼叫“ super() ”方法的情況下

 ...
class Son(Father):
    def __init__(self, first_name, last_name, age, hobby):
        self.age = age
        self.hobby = hobby
...

如果您嘗試在此時呼叫 get\_info 方法,則會導致產生 AttributeError ,因為 self.first\_nameself.last\_name 屬性尚未初始化。

/bc/images/trying-to-use-parent-attributes-without-super.jpg

在類別方法中使用 super()

人們不僅可以在建構函數過程的範圍內使用 super() 函數,還可以在一系列不同的方法中使用 super() 函數來增強或取代父類別方法方法的功能。

 class Father:
    def speak(self):
        return "Hello from Father"

class Son(Father):
    def speak(self):
        # Call the parent class's speak method using super()
        parent_greeting = super().speak()
        return f"Hello from Son\n{parent_greeting}"

# Create an instance of the Son class
son = Son()

# Call the speak method of the Son class
son_greeting = son.speak()

print(son_greeting)

Python 中的 Son 類別被設計為從其父類別或 Father 類別繼承屬性和方法,包括 speak() 方法。透過利用 Son 類別的 spoke() 方法中的 super().speak() 函數,它可以有效地呼叫 Father 類別的原始 speak() 方法,同時還可以合併任何 Son 類別特有的附加資訊或訊息。

/bc/images/using-super-in-class-mthod.jpg

如果一個方法覆寫另一個方法而不使用提供的「 super() 」函數,則父類別的預期功能將不會被執行。因此,由於全新且獨特的方法取代了原始功能,這可能會導致意外行為。

了解方法解析順序

方法解析順序 (MRO) 是指優先權層次結構,它決定了 Python 在處理涉及多重繼承的複雜類別結構時搜尋方法和屬性的順序。這種機制確保根據各自父類別中的可用選項呼叫適當的方法,從而解決由於重疊定義而引起的任何潛在的歧義。

 class Nigeria():
    def culture(self):
        print("Nigeria's culture")

class Africa():
   def culture(self):
       print("Africa's culture") 

當實例化 Lagos 類別並呼叫其文化方法時,會發生許多有助於物件整體功能的事件。程式碼執行經歷幾個階段,包括資料操作、從外部來源檢索資訊以及應用各種演算法根據使用者提供的輸入參數或建構函數中設定的預設值來分析文化方面。最終結果是對以拉各斯類為代表的指定城市文化屬性的全面評估。

Python 首先在「Lagos」類別本身中搜尋「culture」方法。如果該方法被發現並且可用,演算法將繼續呼叫它。然而,如果不存在這樣的方法或無法存取該方法,則該過程會前進到後續階段。

如果 Lagos 類別沒有 culture() 方法,Python 將在類別層次結構的基底類別中搜尋該方法,從冒號 (:) 後面列出的那些方法開始,這些方法由拉各斯類。在此範例中,「Lagos」類別被定義為首先從「Africa」類別繼承,然後從「Nigeria」類別繼承。因此,如果 Lagos 類別不包含自己的 culture() 方法的實現,Python 將在搜尋 Nigeria 類別之前嘗試在 Africa 類別中尋找該方法。

在給定類別層次結構中搜尋特定於文化的方法透過一系列嵌套類別進行,如果在其中找到所需的方法,則檢查每個後續類別。如果在最初的查詢層級(即非洲類)沒有發現該方法,Python 會將其焦點轉移到層次結構中的下一個最高類,在本例中對應於尼日利亞類。當一個人沿著類樹下降時,這個過程會不斷重複,從最一般的到最不具體的,直到所尋找的方法無法在任何遇到的超類中找到。此時,會引發異常以表示搜尋結果不成功。

/bc/images/the-mothod-resolution-order.jpg

拉各斯的方法解析順序 (MRO) 以線性方式顯示,從左側開始向右推進。

常見陷阱和最佳實踐

在使用 super() 函數時,重要的是要意識到某些潛在的失誤,以確保流暢有效的體驗。

⭐ 請注意方法解析順序,尤其是在多重繼承場景中。如果您需要使用複雜的多重繼承,您應該熟悉Python用來確定MRO的C3線性化演算法

應避免類別層次結構中的循環依賴關係,因為它們可能會導致不穩定且難以預測的行為。

當處理涉及使用 super() 函數的複雜類別層次結構時,維護清晰且記錄良好的程式碼庫至關重要。這不僅確保了正確的功能,而且還促進了將來可能需要處理或修改程式碼的其他開發人員之間的理解。透過提供簡潔而資訊豐富的註釋,您可以增強專案的可讀性和可維護性,促進協作並減少潛在的錯誤或混亂。

正確使用 super()

Python 對「super()」函數的利用代表了其物件導向程式設計範式的一個不可或缺的方面,特別是在促進繼承和方法重寫方面。掌握與此功能實體相關的複雜性並遵守既定的最佳實踐,可以在 Python 生態系統中開發更持久、更豐富的軟體應用程式。