python super的使用方法及實(shí)例詳解
功能
super功能:super函數(shù)是子類用于調(diào)用父類(超類)的一個(gè)方法。
用法
1.在子類 __init__() 方法中正確的初始化父類,保證相同的基類只初始化一次。
2.覆蓋特殊方法。
3.解決多重繼承中,子類重復(fù)調(diào)用父類方法的問題。
注意
super()繼承只能用于新式類,用于經(jīng)典類時(shí)就會(huì)報(bào)錯(cuò)。
新式類:必須有繼承的類,如果無繼承的,則繼承object
經(jīng)典類:沒有父類,如果此時(shí)調(diào)用super就會(huì)出現(xiàn)錯(cuò)誤:『super() argument 1 must be type, not classobj)
在子類__init__()方法中正確初始化父類,保證相同的基類只初始化一次
假如說在父類中實(shí)現(xiàn)了一個(gè)方法,你想在子類中使用父類的這個(gè)方法并且做一定擴(kuò)展但是又不想完全重寫,并且這個(gè)場(chǎng)景中的繼承屬于多繼承,那么super()就出場(chǎng)了,可以實(shí)現(xiàn)方法的增量修改。
A(父類)有x屬性,B(子類)想添加y屬性:
class A(object):
def __init__(self,x):
self.x = x
class B(A):
def __init__(self,x,y):
super(B,self,).__init__(x)
self.y = y
a = A(2)
b = B(2,4)
print(a.x)
print(b.x,b.y)
覆蓋Python特殊方法
class Proxy:
def __init__(self, obj):
self._obj = obj
# Delegate attribute lookup to internal obj
def __getattr__(self, name):
return getattr(self._obj, name)
# Delegate attribute assignment
def __setattr__(self, name, value):
if name.startswith('_'):
super().__setattr__(name, value) # Call original __setattr__
else:
setattr(self._obj, name, value)
在上面代碼中,__setattr__() 的實(shí)現(xiàn)包含一個(gè)名字檢查。 如果某個(gè)屬性名以下劃線(_)開頭,就通過 super() 調(diào)用原始的 __setattr__() , 否則的話就委派給內(nèi)部的代理對(duì)象 self._obj 去處理。 這看上去有點(diǎn)意思,因?yàn)榫退銢]有顯式的指明某個(gè)類的父類, super() 仍然可以有效的工作。
解決多重繼承中,子類重復(fù)調(diào)用父類方法的問題
class Base:
def __init__(self):
print('Base.__init__')
class A(Base):
def __init__(self):
Base.__init__(self)
print('A.__init__')
盡管對(duì)于大部分代碼而言這么做沒什么問題,但是在更復(fù)雜的涉及到多繼承的代碼中就有可能導(dǎo)致很奇怪的問題發(fā)生。 比如,考慮如下的情況:
class Base:
def __init__(self):
print('Base.__init__')
class A(Base):
def __init__(self):
Base.__init__(self)
print('A.__init__')
class B(Base):
def __init__(self):
Base.__init__(self)
print('B.__init__')
class C(A,B):
def __init__(self):
A.__init__(self)
B.__init__(self)
print('C.__init__')
如果你運(yùn)行這段代碼就會(huì)發(fā)現(xiàn) Base.__init__() 被調(diào)用兩次,如下所示:
>>> c = C() Base.__init__ A.__init__ Base.__init__ B.__init__ C.__init__ >>>
可能兩次調(diào)用 Base.__init__() 沒什么壞處,但有時(shí)候卻不是。 另一方面,假設(shè)你在代碼中換成使用 super() ,結(jié)果就很完美了:
class Base:
def __init__(self):
print('Base.__init__')
class A(Base):
def __init__(self):
super().__init__()
print('A.__init__')
class B(Base):
def __init__(self):
super().__init__()
print('B.__init__')
class C(A,B):
def __init__(self):
super().__init__() # Only one call to super() here
print('C.__init__')
運(yùn)行這個(gè)新版本后,你會(huì)發(fā)現(xiàn)每個(gè) __init__() 方法只會(huì)被調(diào)用一次了:
>>> c = C() Base.__init__ B.__init__ A.__init__ C.__init__ >>>
為了弄清它的原理,我們需要花點(diǎn)時(shí)間解釋下Python是如何實(shí)現(xiàn)繼承的。 對(duì)于你定義的每一個(gè)類,Python會(huì)計(jì)算出一個(gè)所謂的方法解析順序(MRO)列表。 這個(gè)MRO列表就是一個(gè)簡(jiǎn)單的所有基類的線性順序表。例如:
>>> C.__mro__ (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>) >>>
為了實(shí)現(xiàn)繼承,Python會(huì)在MRO列表上從左到右開始查找基類,直到找到第一個(gè)匹配這個(gè)屬性的類為止。
而這個(gè)MRO列表的構(gòu)造是通過一個(gè)C3線性化算法來實(shí)現(xiàn)的。 我們不去深究這個(gè)算法的數(shù)學(xué)原理,它實(shí)際上就是合并所有父類的MRO列表并遵循如下三條準(zhǔn)則:
- 子類會(huì)先于父類被檢查
- 多個(gè)父類會(huì)根據(jù)它們?cè)诹斜碇械捻樞虮粰z查
- 如果對(duì)下一個(gè)類存在兩個(gè)合法的選擇,選擇第一個(gè)父類
老實(shí)說,你所要知道的就是MRO列表中的類順序會(huì)讓你定義的任意類層級(jí)關(guān)系變得有意義。
當(dāng)你使用 super() 函數(shù)時(shí),Python會(huì)在MRO列表上繼續(xù)搜索下一個(gè)類。 只要每個(gè)重定義的方法統(tǒng)一使用 super() 并只調(diào)用它一次, 那么控制流最終會(huì)遍歷完整個(gè)MRO列表,每個(gè)方法也只會(huì)被調(diào)用一次。 這也是為什么在第二個(gè)例子中你不會(huì)調(diào)用兩次 Base.__init__() 的原因。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
python里使用正則表達(dá)式的組嵌套實(shí)例詳解
這篇文章主要介紹了python里使用正則表達(dá)式的組嵌套實(shí)例詳解的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下2017-10-10
Qt5.14 與 OpenCV4.5 教程之圖片增強(qiáng)效果
這篇文章主要介紹了Qt5.14 與 OpenCV4.5 教程之圖片增強(qiáng)效果的實(shí)現(xiàn),本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-11-11
Python實(shí)踐之使用Pandas進(jìn)行數(shù)據(jù)分析
在數(shù)據(jù)分析領(lǐng)域,Python的Pandas庫(kù)是一個(gè)非常強(qiáng)大的工具。這篇文章將為大家詳細(xì)介紹如何使用Pandas進(jìn)行數(shù)據(jù)分析,希望對(duì)大家有所幫助2023-04-04
django中的自定義分頁(yè)器的實(shí)現(xiàn)示例
本文主要介紹了django中的自定義分頁(yè)器的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
Python數(shù)據(jù)預(yù)處理常用的5個(gè)技巧
大家好,本篇文章主要講的是Python數(shù)據(jù)預(yù)處理常用的5個(gè)技巧,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下2022-02-02
Python二進(jìn)制文件讀取并轉(zhuǎn)換為浮點(diǎn)數(shù)詳解
這篇文章主要介紹了Python二進(jìn)制文件讀取并轉(zhuǎn)換為浮點(diǎn)數(shù)詳解,用python讀取二進(jìn)制文件,這里主要用到struct包,而這個(gè)包里面的方法主要是unpack、pack、calcsize。,需要的朋友可以參考下2019-06-06

