新式類 VS 經典類
一、概述
Python中支持多繼承,也就是一個子類可以繼承多個父類/基類。當一個調用一個自身沒有定義的屬性時,它是按照何種順序去父類中尋找的呢?尤其是當眾多父類中都包含有同名的屬性,這就涉及到新式類 和 經典類的區別。
二、多繼承
1 class Food(object): 2 3 def __init__(self, name, color): 4 self.name = name 5 self.color = color 6 7 def eatable(self): 8 print("%s can be eaten.View Code" % self.name) 9 10 def appearance(self): 11 print(‘The color of the %s is %s.‘ % (self.name, self.color)) 12 13 14 class Fruits(object): 15 16 def __init__(self, name, nutrition): 17 self.name = name 18 self.nutrition = nutrition 19 20 def info(self): 21 print("%s can supply much %s." % (self.name, self.nutrition)) 22 23 24 class Salad(Fruits, Food): # 繼承多個父類 25 26 def __init__(self, name, nutrition, color, tasty): 27 super(Salad, self).__init__(name, nutrition) 28 Food.__init__(self, name, color) 29 self.tasty = tasty 30 31def taste(self): 32 print("%s is a little %s." % (self.name, self.tasty)) 33 34 35 obj = Salad(‘orange‘, ‘VC‘, ‘orange‘, ‘sour‘) 36 37 obj.eatable() 38 obj.appearance() 39 obj.info() 40 obj.taste()
上例中的Salad(Fruits,Food)繼承了Fruits和Food兩個父類。
supper()函數為新式類的方法,采用新式類要求最頂層的父類一定要繼承於object,這樣就可以用super()函數來調用父類的init()等函數。每個父類都執行且執行一次,並不會出現重復調用的情況。采用super()方法時,會自動找到第一個多繼承中的第一父類。
但是如果想要繼續調用其它父類init()函數或兩個父類的同名函數時,就要用經典類的調用方法了,即 父類名.__init__(self,參數),如上例。
三、經典類 VS 新式類的繼承順序
3.1 新式類
1、新式類定義時必須繼承object類,繼承了object類的就叫做 新式類
class Fruits(object): ‘新式類‘ pass
2、采用super()函數類調用父類的 init()等函數
super(子類名,self).__init__(參數1,參數2,..)
3、調用父類中相同屬性或者方法的順序
新式類的調用順序為: 廣度優先查詢
子類先在自己的所有父類中從左至右查詢,如果沒有需要的方法或屬性,再到本身父類的父類中去查詢。
代碼如下:
1.調用本身屬性
1 class A(object): 2 def __init__(self): 3 self.n = "A" 4 5 6 class B(A): 7 8 def __init__(self): 9 super(B, self).__init__() 10 self.n = "B" 11 12 13 class C(A): 14 15 def __init__(self): 16 super(C, self).__init__() 17 self.n = "C" 18 19 20 class D(B, C): 21 22 def __init__(self): 23 super(D, self).__init__() 24 self.n = "D" 25 26 27 d = D() 28 print(d.n) 29 30 #輸出 31 DView Code
2.註釋D中的代碼,獲得B
1 class A(object): 2 def __init__(self): 3 self.n = "A" 4 5 6 class B(A): 7 8 def __init__(self): 9 super(B, self).__init__() 10 self.n = "B" 11 12 13 class C(A): 14 15 def __init__(self): 16 super(C, self).__init__() 17 self.n = "C" 18 19 20 class D(B, C): 21 22 # def __init__(self): 23 # super(D, self).__init__() 24 # self.n = "D" 25 pass 26 27 d = D() 28 print(d.n) 29 30 #輸出 31 BView Code
3.註釋B中的代碼,獲得C
1 class A(object): 2 def __init__(self): 3 self.n = "A" 4 5 6 class B(A): 7 8 # def __init__(self): 9 # super(B, self).__init__() 10 # self.n = "B" 11 pass 12 13 14 class C(A): 15 16 def __init__(self): 17 super(C, self).__init__() 18 self.n = "C" 19 20 21 class D(B, C): 22 23 # def __init__(self): 24 # super(D, self).__init__() 25 # self.n = "D" 26 pass 27 28 d = D() 29 print(d.n) 30 31 #輸出 32 CView Code
4.註釋C中的代碼,獲得A
1 class A(object): 2 def __init__(self): 3 self.n = "A" 4 5 6 class B(A): 7 8 # def __init__(self): 9 # super(B, self).__init__() 10 # self.n = "B" 11 pass 12 13 14 class C(A): 15 # 16 # def __init__(self): 17 # super(C, self).__init__() 18 # self.n = "C" 19 pass 20 21 22 class D(B, C): 23 24 # def __init__(self): 25 # super(D, self).__init__() 26 # self.n = "D" 27 pass 28 29 d = D() 30 print(d.n) 31 32 #輸出 33 AView Code
3.2 經典類
1、經典類定義,什麽都不繼承
class Fruit: ‘經典類‘ pass
2、繼承父類的init()等函數或屬性
父類名.__init__(self, 參數1,參數2,....)
3、調用父類中相同屬性或者方法的順序
在 Python3 中,多繼承的查詢順序都是 廣度優先查詢
經典類的調用順序為: 深度優先查詢
子類會沿著父類的父類這樣的順序查詢,如果都沒有,會返回查找另一個父類。
代碼如下:
1.調用本身的屬性
1 class A:#經典類 2 def __init__(self): 3 self.n = "A" 4 5 class B(A): 6 pass 7 def __init__(self): 8 self.n = "B" 9 10 class C(A): 11 def __init__(self): 12 self.n = "C" 13 14 class D(B,C): 15 def __init__(self): 16 self.n = "D" 17 18 d = D() 19 print(d.n) 20 21 #輸出 22 D 23 24 全部代碼View Code
2. 註釋D中的代碼,獲得B
1 class A: 2 def __init__(self): 3 self.n = "A" 4 5 class B(A): 6 def __init__(self): 7 self.n = "B" 8 9 class C(A): 10 def __init__(self): 11 self.n = "C" 12 13 class D(B,C): 14 pass 15 16 d = D() 17 print(d.n) 18 19 #輸出 20 BView Code
3.註釋B中的代碼,獲得A
1 class A: 2 def __init__(self): 3 self.n = "A" 4 5 class B(A): 6 pass 7 8 class C(A): 9 def __init__(self): 10 self.n = "C" 11 12 class D(B,C): 13 pass 14 15 d = D() 16 print(d.n) 17 18 #輸出 19 AView Code
4.註釋A中的代碼,獲得C
1 class A: 2 pass 3 4 class B(A): 5 pass 6 7 class C(A): 8 def __init__(self): 9 self.n = "C" 10 11 class D(B,C): 12 pass 13 14 d = D() 15 print(d.n) 16 17 #輸出 18 CView Code
四、總結
1、新式類繼承object類,經典類不繼承任何類
2、新式類用super關鍵字繼承構造方法,經典類用 父類.__init(self)來繼承
3、新式類:廣度優先查詢,經典類:深度優先查詢(因為新式類講究的是新,所以要找最近的,最新的;然後經典的講究古老,所以更遠更深的)
4、值得註意的是,我們上面是在python2中做的,在python3中不管是經典類還是新式類,都是采用的是廣度優先查詢,已經廢棄2中的深度查詢了
新式類 VS 經典類