Python 在子類中呼叫父類方法詳解(單繼承、多層繼承、多重繼承)
測試環境:
win7 64位
Python版本:Python 3.3.5
程式碼實踐:
1、在子類中通過“類名”呼叫父類的方法
class FatherA:
def __init__(self):
print('init action in father class A')
class SubClassB(FatherA):
def __init__(self):
print('init action in subclass B')
FatherA.__init__(self) # 在子類中呼叫父類的方法:父類名.方法名稱(引數)
if __name__ == '__main__':
b = SubClassB()
執行結果:
>>>
init action in subclass B
init action in father class A
缺點:當一個子類的父類發生變化時(如類SubClassB的父類由FatherA變為FatherD時),必須遍歷整個類定義,把子類中所有的父類類名全部替換過來
2、在子類中通過“super”方法呼叫父類的方法
場景1、單層繼承
class FatherA:
def __init__(self):
print('init action in father class A' )
class SubClassB(FatherA):
def __init__(self):
print('init action in father class B')
super().__init__() # 在子類中呼叫父類的方法:super().方法名稱(引數)
if __name__ == '__main__':
b = SubClassB()
class FatherA:
def __init__(self):
print('init action in father class A' )
class SubClassB(FatherA):
def __init__(self):
print('init action in subclass B')
super(SubClassB, self).__init__() # 在子類中呼叫父類的方法:super(type, obj).方法名稱(引數)
if __name__ == '__main__':
b = SubClassB()
執行結果:
>>>
init action in father class B
init action in father class A
說明:
1、super(type, obj),其中obj必須是type型別、type子類型別的例項,否則會報錯:
TypeError: super(type, obj): obj must be an instance or subtype of type
2、super().init() 效果等同 super(SubClassB, self). init()
場景2、多層繼承
實驗1:
class FatherA:
def __init__(self):
print('init action in father class A')
class SubClassB(FatherA):
def __init__(self):
print('init action in subclass B')
super().__init__()
class SubClassC(SubClassB):
def __init__(self):
print('init action in subclass C')
super().__init__()
if __name__ == '__main__':
b = SubClassC()
執行結果:
>>>
init action in subclass C
init action in subclass B
init action in father class A
對比實驗1-1:
class FatherA:
def __init__(self):
print('init action in father class A')
class SubClassB(FatherA):
def __init__(self):
print('init action in subclass B')
super().__init__()
class SubClassC(SubClassB):
def __init__(self):
print('init action in subclass C')
super(SubClassB, self).__init__()
if __name__ == '__main__':
b = SubClassC()
執行結果:
>>>
init action in subclass C
init action in father class A
>>>
對比實驗1-2:
class FatherA:
def __init__(self):
print('init action in father class A')
class SubClassB(FatherA):
def __init__(self):
print('init action in subclass B')
super().__init__()
class SubClassC(SubClassB):
def __init__(self):
print('init action in subclass C')
super(FatherA, FatherA).__init__(self) # 在子類中呼叫父類的方法:super(type, type).方法名稱(引數)
if __name__ == '__main__':
b = SubClassC()
說明:可把 super(FatherA, FatherA).init(self) 換成:
super(FatherA, self).init()
或
super(FatherA, SubClassB).init(self)
或
super(FatherA, SubClassC).init(self)
注意:以上這種情況,必須給init傳遞引數self,否則會報錯:
TypeError: init() missing 1 required positional argument: ‘self’
執行結果:
>>>
init action in subclass C
>>>
說明:super(type1, type2) ,type2必須和type1相同型別,或者其子類型別
實驗2:
class FatherA:
def __init__(self):
print('init action in father class A')
class SubClassB(FatherA):
def __init__(self):
print('init action in subclass B')
super().__init__()
class SubClassC(SubClassB):
def __init__(self):
print('init action in subclass C')
super().__init__()
class SubClassD(SubClassC):
def __init__(self):
print('init action in subclass D')
super().__init__()
if __name__ == '__main__':
b = SubClassD()
執行結果:
>>>
init action in subclass D
init action in subclass C
init action in subclass B
init action in father class A
對比實驗2-1:
class FatherA:
def __init__(self):
print('init action in father class A')
class SubClassB(FatherA):
def __init__(self):
print('init action in subclass B')
super().__init__()
class SubClassC(SubClassB):
def __init__(self):
print('init action in subclass C')
super().__init__()
class SubClassD(SubClassC):
def __init__(self):
print('init action in subclass D')
super(SubClassB, self).__init__()
if __name__ == '__main__':
b = SubClassD()
執行結果:
>>>
init action in subclass D
init action in father class A
>>>
對比實驗2-2:
class FatherA:
def __init__(self):
print('init action in father class A')
class SubClassB(FatherA):
def __init__(self):
print('init action in subclass B')
super().__init__()
class SubClassC(SubClassB):
def __init__(self):
print('init action in subclass C')
super().__init__()
class SubClassD(SubClassC):
def __init__(self):
print('init action in subclass D')
super(SubClassC, self).__init__()
if __name__ == '__main__':
b = SubClassD()
執行結果:
>>>
init action in subclass D
init action in subclass B
init action in father class A
通過對比實驗2-1, 2-2,可看出super(type[,type2_or_obj]),type決定了super呼叫方法所在的父類–type的父類(如果有的話),即type決定了前往哪個父類呼叫指定的方法
場景3、多重繼承
實驗1:
class FatherA:
def __init__(self):
print('init action in father class A')
class FatherB:
def __init__(self):
print('init action in father class B')
class SubClassC(FatherA, FatherB):
def __init__(self):
print('init action in subclass C')
super(FatherB).__init__()
if __name__ == '__main__':
b = SubClassC()
執行結果:
>>>
init action in subclass C
對比實驗1-1:
class FatherA:
def __init__(self):
print('init action in father class A')
class FatherB:
def __init__(self):
print('init action in father class B')
class SubClassC(FatherB, FatherA):
def __init__(self):
print('init action in subclass C')
super().__init__()
if __name__ == '__main__':
b = SubClassC()
執行結果:
>>>
init action in subclass C
init action in father class B
>>>
對比實驗1-2:
class FatherA:
def __init__(self):
print('init action in father class A')
class FatherB:
def __init__(self):
print('init action in father class B')
class SubClassC(FatherA, FatherB):
def __init__(self):
print('init action in subclass C')
super().__init__()
if __name__ == '__main__':
b = SubClassC()
執行結果:
>>>
init action in subclass C
init action in father class A
>>>
對比實驗1-3:
class FatherA:
def __init__(self):
print('init action in father class A')
class FatherB:
def __init__(self):
print('init action in father class B')
class SubClassC(FatherA, FatherB):
def __init__(self):
print('init action in subclass C')
super(FatherB).__init__()
if __name__ == '__main__':
b = SubClassC()
>>> ================================ RESTART ================================
>>>
init action in subclass C
對比實驗1-4:
class FatherA:
def __init__(self):
print('init action in father class A')
def testfn(self, arg):
print('testfn in father class A')
class FatherB:
def __init__(self):
print('init action in father class B')
def testfn(self):
print('testfn in father class B')
class SubClassC(FatherA, FatherB):
def __init__(self):
print('init action in subclass C')
super().testfn()
if __name__ == '__main__':
b = SubClassC()
執行結果:
>>>
init action in subclass C
Traceback (most recent call last):
File "C:/Users/Administrator/Desktop/1.py", line 21, in
b = SubClassC()
File "C:/Users/Administrator/Desktop/1.py", line 18, in __init__
super().testfn()
TypeError: testfn() missing 1 required positional argument: 'arg'
>>>
對比實驗1-5:
class FatherA:
def __init__(self):
print('init action in father class A')
def testfn(self):
print('testfn in father class A')
class FatherB:
def __init__(self):
print('init action in father class B')
def testfn(self, arg):
print('testfn in father class B')
class SubClassC(FatherA, FatherB):
def __init__(self):
print('init action in subclass C')
super().testfn()
if __name__ == '__main__':
b = SubClassC()
執行結果:
>>>
init action in subclass C
testfn in father class A
說明:通過對比實驗1-1,1-2,1-3,1-4,1-5可以看出,子類水平方向上,繼承多個父類,以super().method(引數)方法呼叫父類的方法,如果不同父類中存在同名方法method(不管引數列表是否相同),則按繼承順序,選擇第一個父類中的方法。,如果想要呼叫多個方法咋辦?如下,通過類名呼叫
class FatherA:
def __init__(self):
print('init action in father class A')
class FatherB:
def __init__(self):
print('init action in father class B')
class SubClassC(FatherA, FatherB):
def __init__(self):
print('init action in subclass C')
FatherA.__init__(self)
FatherB.__init__(self)
if __name__ == '__main__':
b = SubClassC()
>>>
init action in subclass C
init action in father class A
init action in father class B
>>>