一、單獨調(diào)用父類的方法
需求:編寫一個類,然后再寫一個子類進行繼承,使用子類去調(diào)用父類的方法1。
使用方法1打印: 胖子老板,來包檳榔。
那么先寫一個胖子老板的父類,執(zhí)行一下:
class FatFather(object):
def __init__(self, name):
print('FatFather的init開始被調(diào)用')
self.name = name
print('FatFather的name是%s' % self.name)
print('FatFather的init調(diào)用結(jié)束')
def main():
ff = FatFather("胖子老板的父親")
運行一下這個胖子老板父類的構(gòu)造方法__init__ 如下:
if __name__ == "__main__":
main()
#FatFather的init開始被調(diào)用
#FatFather的name是胖子老板的父親
#FatFather的init調(diào)用結(jié)束
好了,那么下面來寫一個子類,也就是胖子老板類,繼承上面的類
# 胖子老板的父類
class FatFather(object):
def __init__(self, name):
print('FatFather的init開始被調(diào)用')
self.name = name
print('調(diào)用FatFather類的name是%s' % self.name)
print('FatFather的init調(diào)用結(jié)束')
# 胖子老板類 繼承 FatFather 類
class FatBoss(FatFather):
def __init__(self, name, hobby):
print('胖子老板的類被調(diào)用啦!')
self.hobby = hobby
FatFather.__init__(self, name) # 直接調(diào)用父類的構(gòu)造方法
print("%s 的愛好是 %s" % (name, self.hobby))
def main():
#ff = FatFather("胖子老板的父親")
fatboss = FatBoss("胖子老板", "打斗地主")
在這上面的代碼中,我使用FatFather.init(self,name)直接調(diào)用父類的方法。
運行結(jié)果如下:
if __name__ == "__main__":
main()
#胖子老板的類被調(diào)用啦!
#FatFather的init開始被調(diào)用
#調(diào)用FatFather類的name是胖子老板
#FatFather的init調(diào)用結(jié)束
#胖子老板 的愛好是 打斗地主
二、super() 方法基本概念
除了直接使用 FatFather.init(self,name) 的方法,還可以使用super()方法來調(diào)用。
那么首先需要看super()方法的描述和語法理解一下super() 方法的使用。
1 描述
super() 函數(shù)是用于調(diào)用父類(超類)的一個方法。super 是用來解決多重繼承問題的,直接用類名調(diào)用父類方法在使用單繼承的時候沒問題,但是如果使用多繼承,會涉及到查找順序(MRO)、重復(fù)調(diào)用(鉆石繼承)等種種問題。
MRO 就是類的方法解析順序表, 其實也就是繼承父類方法時的順序表。
2 語法
以下是 super() 方法的語法:
super(type[, object-or-type])
參數(shù)
-
type – 類
-
object-or-type – 類,一般是 self
Python3.x 和 Python2.x 的一個區(qū)別是: Python 3 可以使用直接使用 super().xxx 代替 super(Class, self).xxx :
Python3.x 實例:
class A:
pass
class B(A):
def add(self, x):
super().add(x)
3 單繼承使用super()
使用super() 方法來改寫剛才胖子老板繼承父類的 init 構(gòu)造方法
# 胖子老板的父類
class FatFather(object):
def __init__(self, name):
print('FatFather的init開始被調(diào)用')
self.name = name
print('調(diào)用FatFather類的name是%s' % self.name)
print('FatFather的init調(diào)用結(jié)束')
# 胖子老板類 繼承 FatFather 類
class FatBoss(FatFather):
def __init__(self, name, hobby):
print('胖子老板的類被調(diào)用啦!')
self.hobby = hobby
#FatFather.__init__(self,name) # 直接調(diào)用父類的構(gòu)造方法
super().__init__(name)
print("%s 的愛好是 %s" % (name, self.hobby))
def main():
#ff = FatFather("胖子老板的父親")
fatboss = FatBoss("胖子老板", "打斗地主")
從上面使用super方法的時候,因為是單繼承,直接就可以使用了。
運行如下:
if __name__ == "__main__":
main()
#胖子老板的類被調(diào)用啦!
#FatFather的init開始被調(diào)用
#調(diào)用FatFather類的name是胖子老板
#FatFather的init調(diào)用結(jié)束
#胖子老板 的愛好是 打斗地主
那么為什么說單繼承直接使用就可以呢?因為super()方法如果多繼承的話,會涉及到一個MRO(繼承父類方法時的順序表) 的調(diào)用排序問題。
下面可以打印一下看看單繼承的MRO順序(FatBoss.__mro__
)。
# 胖子老板的父類
class FatFather(object):
def __init__(self, name):
print('FatFather的init開始被調(diào)用')
self.name = name
print('調(diào)用FatFather類的name是%s' % self.name)
print('FatFather的init調(diào)用結(jié)束')
# 胖子老板類 繼承 FatFather 類
class FatBoss(FatFather):
def __init__(self, name, hobby):
print('胖子老板的類被調(diào)用啦!')
self.hobby = hobby
#FatFather.__init__(self,name) # 直接調(diào)用父類的構(gòu)造方法
super().__init__(name)
print("%s 的愛好是 %s" % (name, self.hobby))
def main():
print("打印FatBoss類的MRO")
print(FatBoss.__mro__)
print()
print("=========== 下面按照 MRO 順序執(zhí)行super方法 =============")
fatboss = FatBoss("胖子老板", "打斗地主")
上面的代碼使用 FatBoss.mro 可以打印出 FatBoss這個類經(jīng)過 python解析器的 C3算法計算過后的繼承調(diào)用順序。
運行如下:
if __name__ == "__main__":
main()
打印FatBoss類的MRO
(<class '__main__.FatBoss'>, <class '__main__.FatFather'>, <class 'object'>)
=========== 下面按照 MRO 順序執(zhí)行super方法 =============
胖子老板的類被調(diào)用啦!
FatFather的init開始被調(diào)用
調(diào)用FatFather類的name是胖子老板
FatFather的init調(diào)用結(jié)束
胖子老板 的愛好是 打斗地主
從上面的結(jié)果 (<class ‘main.FatBoss’>, <class ‘main.FatFather’>, <class ‘object’>) 可以看出,super() 方法在 FatBoss 會直接調(diào)用父類是 FatFather ,所以單繼承是沒問題的。
那么如果多繼承的話,會有什么問題呢?
4 多繼承使用super()
假設(shè)再寫一個胖子老板的女兒類,和 胖子老板的老婆類,此時女兒需要同時繼承 兩個類(胖子老板類,胖子老板老婆類)。
因為胖子老板有一個愛好,胖子老板的老婆需要干活干家務(wù),那么女兒需要幫忙同時兼顧。
此時女兒就是需要繼承使用這兩個父類的方法了,那么該如何去寫呢?
下面來看看實現(xiàn)代碼:
# 胖子老板的父類
class FatFather(object):
def __init__(self, name, *args, **kwargs):
print()
print("=============== 開始調(diào)用 FatFather ==================")
print('FatFather的init開始被調(diào)用')
self.name = name
print('調(diào)用FatFather類的name是%s' % self.name)
print('FatFather的init調(diào)用結(jié)束')
print()
print("=============== 結(jié)束調(diào)用 FatFather ==================")
# 胖子老板類 繼承 FatFather 類
class FatBoss(FatFather):
def __init__(self, name, hobby, *args, **kwargs):
print()
print("=============== 開始調(diào)用 FatBoss ==================")
print('胖子老板的類被調(diào)用啦!')
#super().__init__(name)
## 因為多繼承傳遞的參數(shù)不一致,所以使用不定參數(shù)
super().__init__(name, *args, **kwargs)
print("%s 的愛好是 %s" % (name, hobby))
print()
print("=============== 結(jié)束調(diào)用 FatBoss =================")
#學(xué)習(xí)中遇到問題沒人解答?小編創(chuàng)建了一個Python學(xué)習(xí)交流群:711312441
# 胖子老板的老婆類 繼承 FatFather類
class FatBossWife(FatFather):
def __init__(self, name, housework, *args, **kwargs):
print()
print("=============== 開始調(diào)用 FatBossWife ===============")
print('胖子老板的老婆類被調(diào)用啦!要學(xué)會干家務(wù)')
#super().__init__(name)
## 因為多繼承傳遞的參數(shù)不一致,所以使用不定參數(shù)
super().__init__(name, *args, **kwargs)
print("%s 需要干的家務(wù)是 %s" % (name, housework))
print()
print("=============== 結(jié)束調(diào)用 FatBossWife ==============")
# 胖子老板的女兒類 繼承 FatBoss FatBossWife類
class FatBossGril(FatBoss, FatBossWife):
def __init__(self, name, hobby, housework):
print('胖子老板的女兒類被調(diào)用啦!要學(xué)會干家務(wù),還要會幫胖子老板斗地主')
super().__init__(name, hobby, housework)
def main():
print("打印FatBossGril類的MRO")
print(FatBossGril.__mro__)
print()
print("=========== 下面按照 MRO 順序執(zhí)行super方法 ===========")
gril = FatBossGril("胖子老板", "打斗地主", "拖地")
運行結(jié)果如下:
if __name__ == "__main__":
main()
打印FatBossGril類的MRO
(<class '__main__.FatBossGril'>, <class '__main__.FatBoss'>,
<class '__main__.FatBossWife'>, <class '__main__.FatFather'>, <class 'object'>)
=========== 下面按照 MRO 順序執(zhí)行super方法 =============
胖子老板的女兒類被調(diào)用啦!要學(xué)會干家務(wù),還要會幫胖子老板斗地主
=============== 開始調(diào)用 FatBoss ======================
胖子老板的類被調(diào)用啦!
=============== 開始調(diào)用 FatBossWife ==================
胖子老板的老婆類被調(diào)用啦!要學(xué)會干家務(wù)
=============== 開始調(diào)用 FatFather ====================
FatFather的init開始被調(diào)用
調(diào)用FatFather類的name是胖子老板
FatFather的init調(diào)用結(jié)束
=============== 結(jié)束調(diào)用 FatFather ===================
胖子老板 需要干的家務(wù)是 拖地
=============== 結(jié)束調(diào)用 FatBossWife =================
胖子老板 的愛好是 打斗地主
=============== 結(jié)束調(diào)用 FatBoss ======================
從上面的運行結(jié)果來看,我特意給每個類的調(diào)用開始以及結(jié)束都進行打印標(biāo)識,可以看到。每個類開始調(diào)用是根據(jù)MRO順序進行開始,然后逐個進行結(jié)束的。還有就是由于因為需要繼承不同的父類,參數(shù)不一定。所以,所有的父類都應(yīng)該加上不定參數(shù)*args , **kwargs ,不然參數(shù)不對應(yīng)是會報錯的。
三、注意事項
-
super().__init__
相對于類名.init,在單繼承上用法基本無差 -
但在多繼承上有區(qū)別,super方法能保證每個父類的方法只會執(zhí)行一次,而使用類名的方法會導(dǎo)致方法被執(zhí)行多次,可以嘗試寫個代碼來看輸出結(jié)果
-
多繼承時,使用super方法,對父類的傳參數(shù),應(yīng)該是由于python中super的算法導(dǎo)致的原因,必須把參數(shù)全部傳遞,否則會報錯
-
單繼承時,使用super方法,則不能全部傳遞,只能傳父類方法所需的參數(shù),否則會報錯文章來源:http://www.zghlxwxcb.cn/news/detail-754040.html
-
多繼承時,相對于使用類名.__init__方法,要把每個父類全部寫一遍, 而使用super方法,只需寫一句話便執(zhí)行了全部父類的方法,這也是為何多繼承需要全部傳參的一個原因文章來源地址http://www.zghlxwxcb.cn/news/detail-754040.html
到了這里,關(guān)于python中super()方法的詳細用法的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!