Python高級編程之繼承問題詳解(super與mro)
本文實例講述了Python高級編程之繼承問題。分享給大家供大家參考,具體如下:
多繼承問題
1.單獨調用父類:
一個子類同時繼承自多個父類,又稱菱形繼承、鉆石繼承。
使用父類名.init(self)方式調用父類時:
例:
class Parent(object):
def __init__(self, name):
self.name = name
print('parent的init結束被調用')
class Son1(Parent):
def __init__(self, name, age):
Parent.__init__(self, name)
self.age = age
print('Son1的init結束被調用')
class Son2(Parent):
def __init__(self, name, gender):
Parent.__init__(self, name)
self.gender = gender
print('Son2的init結束被調用')
class Grandson(Son1, Son2):
def __init__(self, name, age, gender):
Son1.__init__(self, name, age) # 單獨調用父類的初始化方法
Son2.__init__(self, name, gender)
print('Grandson的init結束被調用')
gs = Grandson('grandson', 12, '男')
執(zhí)行結果:

可以看出使用父類名.init(self)方式調用父類時,parent父類被調用了兩次,此方法對于多繼承不太合適。
2.MRO順序:
上述代碼,我們發(fā)現(xiàn)由于多繼承情況,parent類被的屬性被構造了兩次,如果在更加復雜的結構下可能更加嚴重。
為了解決這個問題,Python官方采用了一個算法將復雜結構上所有的類全部都映射到一個線性順序上,而根據這個順序就能夠保證所有的類都會被構造一次。
這個順序就是MRO順序。
MRO順序采用C3算法廣度優(yōu)先遍歷。
使用方法: 類名.mro()或類名.mro()

3.super調用父類:
使用super().init()方式調用父類時:
例:
class Parent(object):
def __init__(self, name, *args, **kwargs): # 為避免多繼承報錯,使用不定長參數,接受參數
self.name = name
print('parent的init結束被調用')
class Son1(Parent):
def __init__(self, name, age, *args, **kwargs): # 為避免多繼承報錯,使用不定長參數,接受參數
self.age = age
super().__init__(name, *args, **kwargs) # 為避免多繼承報錯,使用不定長參數,接受參數
print('Son1的init結束被調用')
class Son2(Parent):
def __init__(self, name, gender, *args, **kwargs): # 為避免多繼承報錯,使用不定長參數,接受參數
self.gender = gender
super().__init__(name, *args, **kwargs) # 為避免多繼承報錯,使用不定長參數,接受參數
print('Son2的init結束被調用')
class Grandson(Son1, Son2):
def __init__(self, name, age, gender):
# 多繼承時,相對于使用類名.__init__方法,要把每個父類全部寫一遍
# 而super只用一句話,執(zhí)行了全部父類的方法,這也是為何多繼承需要全部傳參的一個原因
# super(Grandson, self).__init__(name, age, gender)
super().__init__(name, age, gender)
print('Grandson的init結束被調用')
gs = Grandson('grandson', 12, '男')
print(Grandson.__mro__)
運行結果:

parent父類只被調用了一次,super方法會按照MRO順序調用下一個父類。
總結:
(1)MRO保證了多繼承情況 每個類只出現(xiàn)一次
(2)super().init相對于類名.init,在單繼承上用法基本無差
(3)但在多繼承上有區(qū)別,super方法能保證每個父類的方法只會執(zhí)行一次,而使用類名的方法會導致方法被執(zhí)行多次
(4)多繼承時,使用super方法,對父類的傳參數,是由于python中super的算法導致的原因,必須把參數全部傳遞,否則會報錯
(5)單繼承時,使用super方法,不能全部傳遞,只能傳父類方法所需的參數,否則會報錯
(6)多繼承時,相對于使用類名.init方法,要把每個父類全部寫一遍, 而使用super方法,只需寫一句話便執(zhí)行了全部父類的方法,這也是為何多繼承需要全部傳參的一個原因
更多關于Python相關內容感興趣的讀者可查看本站專題:《Python面向對象程序設計入門與進階教程》、《Python數據結構與算法教程》、《Python函數使用技巧總結》、《Python字符串操作技巧匯總》、《Python編碼操作技巧總結》及《Python入門與進階經典教程》
希望本文所述對大家Python程序設計有所幫助。
相關文章
關于windos10環(huán)境下編譯python3版pjsua庫的問題
pjsua默認綁定的python版本是python 2.4,使用起來有諸多限制,希望可以使用python3調用pjsua的庫實現(xiàn)軟電話的基礎功能。這篇文章主要介紹了windos10環(huán)境下編譯python3版pjsua庫,需要的朋友可以參考下2021-10-10

