在Python面向對象編程中,我們經常需要調用父類的構造函數,而調用父類構造函數的一種常用方法是使用super()函數,其搭配的關鍵字是__init__()函數。
一、super()函數的概念
super()函數用於調用父類中的方法,可以避免在子類實現中重複寫出父類的方法名,實現了代碼復用與維護的便利。
當父類中出現同名函數的時候,使用super()可以保證調用了正確的函數。這是因為super()會按照方法解析順序(MRO)的順序來查找父類中的方法,而不是在當前類中查找。
MRO是一種線性化的方法解析順序,它定義了子類中的方法搜索順序,每個類都有一個MRO列表,按照從左至右,深度優先的順序排列。
class A:
def __init__(self):
print('調用A類構造函數')
class B(A):
def __init__(self):
super().__init__()
print('調用B類構造函數')
b = B()
運行結果:
調用A類構造函數 調用B類構造函數
上例中,子類B繼承自父類A,並在構造函數中調用了父類A的構造函數。在調用super().__init__()時,會調用父類A的構造函數,輸出「調用A類構造函數」的信息,然後再執行自身的構造函數,輸出「調用B類構造函數」的信息。
二、super()函數使用時應注意的問題
1. super()函數的參數
super()函數有兩種常見的調用形式,一種是super(當前類名, self);另一種是super(父類名, 子類實例)。
第一種調用形式中,當前類名可以省略,直接傳入self,Python解釋器會自動根據當前類確定要調用的父類。
class A:
def foo(self):
print('調用A類方法')
class B(A):
def foo(self):
super().foo()
b = B()
b.foo()
運行結果:
調用A類方法
上例中,子類B繼承自父類A,重寫了foo方法,並在foo方法中使用super().foo()調用了父類A的foo方法。
第二種調用形式中,可以手動指定要調用的父類名稱,Python解釋器會根據該名稱按照類的繼承關係來確定要調用的父類。
class A:
def foo(self):
print('調用A類方法')
class B(A):
def foo(self):
super(A, self).foo()
b = B()
b.foo()
運行結果:
調用A類方法
上例中,子類B繼承自父類A,重寫了foo方法,並在foo方法中使用super(A, self).foo()調用了父類A的foo方法。
2. super()函數與多繼承的關係
在多繼承的情況下,使用super()函數調用的是MRO列表中的下一個類的方法,而不是當前類的父類的方法。
class A:
def foo(self):
print('調用A類方法')
class B:
def foo(self):
print('調用B類方法')
class C(A, B):
def foo(self):
super().foo()
c = C()
c.foo()
運行結果:
調用B類方法
上例中,子類C繼承自父類A和B,並在foo方法中使用super().foo()調用了父類A和B的foo方法。在Python中,多繼承使用DFS演算法創建MRO列表。因此MRO列表中的順序為[C, A, B, object],super()函數調用的是MRO列表中的下一個類的方法,即B類的foo方法。
三、總結
super()函數是Python中非常重要的一個函數,用於調用父類的方法。在使用時應注意其參數的傳入方式,以及在多繼承的情況下的使用。
合理使用super()函數可以提高代碼的可讀性、減少代碼重複和維護成本,是每個Python工程師都需要掌握的基本技能。
原創文章,作者:AJVI,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/140637.html