一文詳解Python中的super?函數(shù)
實戰(zhàn)場景
經(jīng)常有朋友問,學(xué) Python 面向?qū)ο髸r,翻閱別人代碼,會發(fā)現(xiàn)一個 super() 函數(shù),那這個函數(shù)的作用到底是什么?
super() 函數(shù)的用途如下,在子類中調(diào)用父類的方法,多用于類的繼承關(guān)系。
其語法格式如下所示:
super(type[, object-or-type])
參數(shù)說明如下:
- type:類,可選參數(shù)
- object-or-type:對象或類,一般為 self,也是可選參數(shù)。
返回值是代理對象。
可以直接查詢官方幫助手冊:
help(super)
輸出信息如下所示:
Help on class super in module builtins:
class super(object)
| super() -> same as super(__class__, <first argument>)
| super(type) -> unbound super object
| super(type, obj) -> bound super object; requires isinstance(obj, type)
| super(type, type2) -> bound super object; requires issubclass(type2, type)
| Typical use to call a cooperative superclass method:
| class C(B):
| def meth(self, arg):
| super().meth(arg)
| This works for class methods too:
| class C(B):
| @classmethod
| def cmeth(cls, arg):
| super().cmeth(arg)
對輸出結(jié)果進行分析之后,可以得到如下結(jié)論:
- super 類是一個繼承自 object 的類,super() 函數(shù)就是對該類的實例化;
- 調(diào)用 super() 實例化之后,返回一個 super 對象;
- super() 參數(shù)有四種搭配,具體看上述輸出;
實戰(zhàn)編碼
單繼承使用
直接看一下單繼承相關(guān)代碼,其中使用類名去調(diào)用父類方法。
class A: def funA(self): print("執(zhí)行 A ,輸出橡皮擦") class B(A): def funB(self): # self 表示 B 類的實例 A.funA(self) print("執(zhí)行 B ,輸出鉛筆") b = B() b.funB()
上述代碼在 B 類中增加了 funB 函數(shù),并且去調(diào)用 A 類中的 funA 函數(shù),此時輸出的內(nèi)容如下所示:
執(zhí)行 A ,輸出橡皮擦
執(zhí)行 B ,輸出鉛筆
如果將上述代碼修改為 super() 函數(shù)調(diào)用父類方法,可以使用下述代碼:
class A: def funA(self): print("執(zhí)行 A ,輸出橡皮擦") class B(A): def funB(self): # 注意 super() 函數(shù)的用法 super().funA() print("執(zhí)行 B ,輸出鉛筆") b = B() b.funB()
上述代碼與之前的運行結(jié)果一致,在單繼承的層級結(jié)構(gòu)中,super 可以直接引用父類,即在子類中不需要使用父類名調(diào)用父類方法,而使用 代理對象(super 對象) 去調(diào)用,這樣的好處就是當(dāng)父類名改變或繼承關(guān)系發(fā)生改變時,我們不需要對調(diào)用進行反復(fù)修改。
接下來看一下多繼承情況下,super() 函數(shù)的實戰(zhàn)場景。
class A: def run(self): print('AAA') class B: def run(self): print('BBB') class C: def run(self): print('CCC') class D(A, B, C): def run(self): super().run() d = D() d.run()
此時輸出的結(jié)果是 AAA,可以看到 super 匹配到的數(shù)據(jù)是 A 類中的 run 函數(shù),也就是最左側(cè)類中的方法,下面修改一下各類中 run 函數(shù)的名稱,使其存在差異。
class A: def run1(self): print('AAA') class B: def run2(self): print('BBB') class C: def run3(self): print('CCC') class D(A, B, C): def run(self): # 調(diào)用 B 中 run2 super().run2() d = D() d.run()
當(dāng)一個類繼承多個類時,如果第一個父類中沒有提供該方法,當(dāng)前類實例就會通過 __mro__ 屬性進行向上搜索,如果到 object 類都沒有檢索到該方法,就會引發(fā) AttributeError 異常。
基于上述邏輯,我們可以擴展一下,使用 super() 函數(shù)中的參數(shù)。
class A: def run(self): print('AAA') class B: def run(self): print('BBB') class C: def run(self): print('CCC') class D(A, B, C): def run(self): # 調(diào)用 C 中 run super(B, self).run() d = D() d.run()
此時輸出的結(jié)果是 CCC,該結(jié)果輸出表示了使用 super 函數(shù)之后,可以使用 super(類,self) 指定以哪個類為起點檢索父類中的方法,上述代碼設(shè)置的 B,就表示從 B 開始檢索,后續(xù)找到了 C 類,其中包含 run() 方法,所以輸出 CCC。
__mro__ 屬性的說明。
MRO 是 method resolution order,即方法解析順序,其本質(zhì)是繼承父類方法時的順序表。在 Python 中可以使用內(nèi)置屬性 __mro__ 查看方法的搜索順序,例如下述代碼,重點查看輸出部分內(nèi)容。
class A: def run(self): print('AAA') class B: def run(self): print('BBB') class C: def run(self): print('CCC') class D(A, B, C): def run(self): # 調(diào)用 C 中 run super(B, self).run() print(D.__mro__)
輸出的結(jié)果如下所示:
(<class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class 'object'>)
你可以修改一下繼承順序,然后得到不同的輸出結(jié)果:
(<class '__main__.D'>, <class '__main__.A'>, <class '__main__.C'>, <class '__main__.B'>, <class 'object'>)
在搜索方法的時候,是按照 __mro__ 的輸出結(jié)果從左到右進行順序查找的,邏輯如下:
- A. 找到方法,停止檢索;
- B. 沒有找到,繼續(xù)檢索下一類;
- C. 如果到最后都沒有找到,程序報錯。
到此這篇關(guān)于一文了解Python中的super 函數(shù)的文章就介紹到這了,更多相關(guān)Python super 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python3+PyInstall+Sciter解決報錯缺少dll、html等文件問題
這篇文章主要介紹了Python3+PyInstall+Sciter解決報錯缺少dll、html等文件問題,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2019-07-07libreoffice python 操作word及excel文檔的方法
這篇文章主要介紹了libreoffice python 操作word及excel文檔的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07Python分割單詞和轉(zhuǎn)換命名法的實現(xiàn)
本文主要介紹了Python分割單詞和轉(zhuǎn)換命名法的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03Python輸出列表(List)不帶中括號和引號的問題及解決方法
這篇文章主要介紹了Python輸出列表(List)不帶中括號和引號的問題及解決方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-02-02python機器學(xué)習(xí)基礎(chǔ)K近鄰算法詳解KNN
這篇文章主要為大家介紹了python機器學(xué)習(xí)基礎(chǔ)K近鄰算法詳解有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2021-11-11