1. 單獨調用父類的方法
# coding=utf-8
print("******多繼承使用類名.__init__ 發生的狀态******")
class Parent(object):
def __init__(self, name):
print('parent的init開始被調用')
self.name = name
print('parent的init結束被調用')
class Son1(Parent):
def __init__(self, name, age):
print('Son1的init開始被調用')
self.age = age
Parent.__init__(self, name)
print('Son1的init結束被調用')
class Son2(Parent):
def __init__(self, name, gender):
print('Son2的init開始被調用')
self.gender = gender
Parent.__init__(self, name)
print('Son2的init結束被調用')
class Grandson(Son1, Son2):
def __init__(self, name, age, gender):
print('Grandson的init開始被調用')
Son1.__init__(self, name, age) # 單獨調用父類的初始化方法
Son2.__init__(self, name, gender)
print('Grandson的init結束被調用')
gs = Grandson('grandson', 12, '男')
print('姓名:', gs.name)
print('年齡:', gs.age)
print('性别:', gs.gender)
print("******多繼承使用類名.__init__ 發生的狀态******\n\n")
運作結果:
******多繼承使用類名.__init__ 發生的狀态******
Grandson的init開始被調用
Son1的init開始被調用
parent的init開始被調用
parent的init結束被調用
Son1的init結束被調用
Son2的init開始被調用
parent的init開始被調用
parent的init結束被調用
Son2的init結束被調用
Grandson的init結束被調用
姓名: grandson
年齡: 12
性别: 男
******多繼承使用類名.__init__ 發生的狀态******
2. 多繼承中super調用有所父類的被重寫的方法
print("******多繼承使用super().__init__ 發生的狀态******")
class Parent(object):
def __init__(self, name, *args, **kwargs): # 為避免多繼承報錯,使用不定長參數,接受參數
print('parent的init開始被調用')
self.name = name
print('parent的init結束被調用')
class Son1(Parent):
def __init__(self, name, age, *args, **kwargs): # 為避免多繼承報錯,使用不定長參數,接受參數
print('Son1的init開始被調用')
self.age = age
super().__init__(name, *args, **kwargs) # 為避免多繼承報錯,使用不定長參數,接受參數
print('Son1的init結束被調用')
class Son2(Parent):
def __init__(self, name, gender, *args, **kwargs): # 為避免多繼承報錯,使用不定長參數,接受參數
print('Son2的init開始被調用')
self.gender = gender
super().__init__(name, *args, **kwargs) # 為避免多繼承報錯,使用不定長參數,接受參數
print('Son2的init結束被調用')
class Grandson(Son1, Son2):
def __init__(self, name, age, gender):
print('Grandson的init開始被調用')
# 多繼承時,相對于使用類名.__init__方法,要把每個父類全部寫一遍
# 而super隻用一句話,執行了全部父類的方法,這也是為何多繼承需要全部傳參的一個原因
# super(Grandson, self).__init__(name, age, gender)
super().__init__(name, age, gender)
print('Grandson的init結束被調用')
print(Grandson.__mro__)
gs = Grandson('grandson', 12, '男')
print('姓名:', gs.name)
print('年齡:', gs.age)
print('性别:', gs.gender)
print("******多繼承使用super().__init__ 發生的狀态******\n\n")
運作結果:
******多繼承使用super().__init__ 發生的狀态******
(<class '__main__.Grandson'>, <class '__main__.Son1'>, <class '__main__.Son2'>, <class '__main__.Parent'>, <class 'object'>)
Grandson的init開始被調用
Son1的init開始被調用
Son2的init開始被調用
parent的init開始被調用
parent的init結束被調用
Son2的init結束被調用
Son1的init結束被調用
Grandson的init結束被調用
姓名: grandson
年齡: 12
性别: 男
******多繼承使用super().__init__ 發生的狀态******
注意:
- 以上2個代碼執行的結果不同
- 如果2個子類中都繼承了父類,當在子類中通過父類名調用時,parent被執行了2次
- 如果2個子類中都繼承了父類,當在子類中通過super調用時,parent被執行了1次
3. 單繼承中super
print("******單繼承使用super().__init__ 發生的狀态******")
class Parent(object):
def __init__(self, name):
print('parent的init開始被調用')
self.name = name
print('parent的init結束被調用')
class Son1(Parent):
def __init__(self, name, age):
print('Son1的init開始被調用')
self.age = age
super().__init__(name) # 單繼承不能提供全部參數
print('Son1的init結束被調用')
class Grandson(Son1):
def __init__(self, name, age, gender):
print('Grandson的init開始被調用')
super().__init__(name, age) # 單繼承不能提供全部參數
print('Grandson的init結束被調用')
gs = Grandson('grandson', 12, '男')
print('姓名:', gs.name)
print('年齡:', gs.age)
#print('性别:', gs.gender)
print("******單繼承使用super().__init__ 發生的狀态******\n\n")
print(Grandson.__mro__)
******單繼承使用super().__init__ 發生的狀态******Grandson的init開始被調用
Son1的init開始被調用
parent的init開始被調用
parent的init結束被調用
Son1的init結束被調用
Grandson的init結束被調用
姓名: grandson
年齡: 12
******單繼承使用super().__init__ 發生的狀态******
(<class '__main__.Grandson'>, <class '__main__.Son1'>, <class '__main__.Parent'>, <class 'object'>)
總結
- super().__init__相對于 類名.__init__,在單繼承上用法基本無差
- 但在多繼承上有差別,super方法能保證每個父類的方法隻會執行一次,而使用類名的方法會導緻父類方法被執行多次,具體看前面的輸出結果
- 多繼承時,使用super方法,對父類的傳參數,應該是由于python中super的算法導緻的原因,必須把參數全部傳遞,否則會報錯
- 單繼承時,使用super方法,則不能全部傳遞,隻能傳父類方法所需的參數,否則會報錯
- 多繼承時,相對于使用 類名.__init__方法,要把每個父類全部寫一遍, 而使用super方法,隻需寫一句話便執行了全部父類的方法,這也是為何多繼承需要全部傳參的一個原因