super的簡(jiǎn)單用法
class Father(object):
def __init__(self, name):
self.name = name
class Son(Father):
def __init__(self, name, age):
# super(Son, self).__init__(name) 完整的調(diào)用方式,后面再詳細(xì)說(shuō)明
super().__init__(name) # 調(diào)用父類的初始化方法
self.age = age # 初始化本類參數(shù)
多繼承中super的使用
class Father(object):
def __init__(self, name, *args):
self.name = name
super().__init__(*args)
class Mother(object):
def __init__(self, age, *args):
self.age = age
super().__init__(*args)
class Son(Father, Mother):
def __init__(self, name, age, gender):
super().__init__(name, age)
self.gender = gender
??super簡(jiǎn)單的說(shuō)是調(diào)用父類的方法,不管是父類的初始化方法還是實(shí)例方法都可以滚粟;但實(shí)質(zhì)并非是這樣,比如Father
類和Mother
類中的super并非都是調(diào)用object
的初始化方法,否則也達(dá)不到初始化Son
實(shí)例的效果中燥。事實(shí)上這與MRO有關(guān),當(dāng)然你可能不會(huì)太明白上例的用法塘偎,請(qǐng)接著往下看疗涉。
關(guān)于MRO
??MRO:method resolution order 是python類繼承方法或?qū)傩缘慕馕鲰樞蚣磳ふ翼樞颍纠缦拢?/p>
class Father(object):
def __init__(self, name, *args):
self.name = name
super().__init__(*args)
class Mother(object):
def __init__(self, age, *args):
self.age = age
super().__init__(*args)
class Son(Father, Mother):
def __init__(self, name, age, gender):
super().__init__(name, age)
self.gender = gender
if __name__ == '__main__':
print(Son.__mro__)
# result: (<class '__main__.Son'>, <class '__main__.Father'>, <class '__main__.Mother'>, <class 'object'>)
??打印 mro
吟秩,結(jié)果是一個(gè)類名組成的元組咱扣,類名在元組中的順序就是python解釋器尋找方法或?qū)傩詴r(shí)查找的順序。
??正如前文所述涵防,調(diào)用父類初始化函數(shù)完整的方式是使用super(Son, self).__init__(name)
闹伪,super中第一個(gè)參數(shù)傳遞Son
即表示調(diào)用mro
元組中類名為Son
后面緊鄰類的初始化方法即Father
類的初始化方法;若不傳遞參數(shù)則默認(rèn)傳遞當(dāng)前類名壮池,所以可以簡(jiǎn)寫為super().__init__(name)
偏瓤。因此使用super實(shí)質(zhì)上調(diào)用的是在mro
元組中排列在當(dāng)前類的后面類中的方法。
??如此一來(lái)我們就可以解釋多繼承中為啥要這樣使用super:首先在Son
類中調(diào)用super傳遞兩個(gè)初始化參數(shù)椰憋,由于沒(méi)有指定類名厅克,所以默認(rèn)為當(dāng)前類名,super().__init__(name, age)
會(huì)按照mro
的順序調(diào)用 Father
中的方法橙依,初始化name
证舟;接著多余的參數(shù)會(huì)通過(guò)*args
傳遞給Father
類的super方法硕旗,此時(shí)按照mro
順序會(huì)調(diào)用Mother
類的初始化方法,初始化age
女责。之后已經(jīng)沒(méi)有多余的參數(shù)了漆枚,*args
為空元組,由于在Mother
中調(diào)用了super所以還是會(huì)執(zhí)行object
類的初始化方式抵知,不過(guò)并不會(huì)產(chǎn)生任何影響浪读。此時(shí)Son
類的實(shí)例初始化完畢。
??當(dāng)然正如我們之前所說(shuō)的那樣辛藻,super中傳遞的類名表示調(diào)用此類名在mro
元組中后面的類中的方法碘橘,所以上面的例子可以這樣改寫:
class Father(object):
def __init__(self, name):
self.name = name
class Mother(object):
def __init__(self, age):
self.age = age
class Son(Father, Mother):
def __init__(self, name, age, gender):
super(Son, self).__init__(name) # 調(diào)用Father的初始化方法
super(Father, self).__init__(age) # 調(diào)用Mother的初始化方法
self.gender = gender
??這樣也可以完成初始化的工作,減少了在父類中傳遞不定參數(shù)的麻煩吱肌,前提是得知道mro
的解析順序痘拆,否則容易傳遞錯(cuò)初始化參數(shù)。