Python中子類調用父類的方法有兩種方法能夠實現:調用父類構造方法,或者使用super函數(兩者不要混用)。
使用“super”時經常會出現代碼“super(FooChild,self).__init__(xxx,xxx)”。那super().__init__()到底要怎么用呢?
為了方便理解,我寫了如下例子驗證用法:
#-*- coding:utf-8 -*-
class A(object): def __init__(self,xing,gender): #!#1 self.namea="aaa" #!#2 self.xing = xing #!#3 self.gender = gender #!#4 def funca(self): print "function a : %s"%self.namea class B(A): def __init__(self,xing,age): #!#5 super(B,self).__init__(xing,age) #!#6(age處應為gender) self.nameb="bbb" #!#7 ##self.namea="ccc" #!#8 ##self.xing = xing.upper() #!#9 self.age = age #!#10 def funcb(self): print "function b : %s"%self.nameb b=B("lin",22) #!#11 print b.nameb print b.namea print b.xing #!#12 print b.age #!#13 b.funcb() b.funca()
通過更改代碼中標記#!#幾行的輸入參數來驗證super的用法,並得出以下結論:
1.B類繼承A類,在B類自己的基礎上可以調用A類所以的方法,代碼最后兩行b.funcb()\b.funca()可以正常運行。
2.A、B同時擁有__init__,B會改寫A中的__init__方法,A類的方法失效,通過注釋(#)掉#!#6行代碼、恢復#89行代碼,運行后可得。
3.super函數可以調用A父類中的屬性,如namea、xing,B類中有同名屬性時,覆蓋A類中的同名屬性。但調用函數時總是先查找它自身的定義,如果沒有定義,則順着繼承鏈向上查找,直到在某個父類中找到為止。
4.B類__init__(#5)參數需大於或等於A父類的__init__方法,因為super初始化了,參數量為父類參數量。
5.super函數原理:super().__init__(xxx,xxx)中的xxx參數為類B(#5)中輸入的參數,但與類A中參數名相對應。如上面那段代碼#6中輸入的是age參數,雖然運行結果並沒錯(因為沒有運行.gender),但是其實這個age參數是賦值到A類的gender參數上的(本文末的第二段代碼有相關例子,代碼加#####處)
6.使用super函數時,可將B子類中(#5)與A類相同的參數依次寫入__init__(xxx)的xxx參數中(注意self參數已在super()中傳入,在__init__()中將隱式傳遞,不需要寫出,也不能寫),之后可再次重寫xxx中參數屬性,#5中多余參數可自定義屬性
class A(object): def __init__(self,xing,gender): self.namea="aaa" self.xing = xing self.gender = gender def funca(self): print "function a : %s"%self.namea class B(A): def __init__(self,xing,gender,age): super(B,self).__init__(xing,age) self.nameb="bbb" ##self.namea="ccc" self.xing = xing.upper() self.age = age + 1 #self.gender = gender.upper() def funcb(self): print "function b : %s"%self.nameb b=B("lin","nan",22) print b.nameb print b.namea print b.xing print b.age b.funcb() b.funca() print b.gender #####
輸出結果:
bbb
aaa
LIN
23
function b : bbb
function a : aaa
22 #####