Python的新式類和舊式類
- 概述:
Python中支援多繼承,也就是一個子類可以繼承多個父類/基類。當一個呼叫一個自身沒有定義的屬性時,它是按照何種順序去父類中尋找的呢?尤其是當眾多父類中都包含有同名的屬性,這就涉及到新式類 和 經典類的區別。
- 多繼承:
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." % 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 31 def 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新式類的繼承順序:
新式類
1、新式類定義時必須繼承object類,繼承了object類的就叫做 新式類
class Fruits(object):
'新式類'
pass
2、採用super()函式類呼叫父類的 init()等函式:
super(子類名,self).__init__(引數1,引數2,..)
3、呼叫父類中相同屬性或者方法的順序
新式類的呼叫順序為: 廣度優先查詢
子類先在自己的所有父類中從左至右查詢,如果沒有需要的方法或屬性,再到本身父類的父類中去查詢。
廣度優先遍歷是先把自己的所有屬性遍歷,再把所有父類遍歷一遍,如果沒有找到需要的屬性,則在對父類的父類進行遍歷,以此類推。
示例如下:
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 D
2.註釋D中的程式碼,獲得B
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 B
3.註釋B中的程式碼,獲得C
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 C
4.註釋C中的程式碼,獲得A
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 A
經典類
1、經典類定義,什麼都不繼承
class Fruit:
'經典類'
pass
2、繼承父類的init()等函式或屬性
父類名.__init__(self, 引數1,引數2,....)
3、呼叫父類中相同屬性或者方法的順序
在 Python3 中,多繼承的查詢順序都是 廣度優先查詢
經典類的呼叫順序為: 深度優先查詢
子類會沿著父類的父類這樣的順序查詢,如果都沒有,會返回查詢另一個父類。
示例如下:
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 全部程式碼
- 註釋D中的程式碼,獲得B
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 B
3.註釋B中的程式碼,獲得A
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 A
4.註釋A中的程式碼,獲得C
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 C
- 總結:
1、新式類繼承object類,經典類不繼承任何類
2、新式類用super關鍵字繼承構造方法,經典類用 父類.init(self)來繼承
3、新式類:廣度優先查詢,經典類:深度優先查詢(因為新式類講究的是新,所以要找最近的,最新的;然後經典的講究古老,所以更遠更深的)
4、值得注意的是,我們上面是在python2中做的,在python3中不管是經典類還是新式類,都是採用的是廣度優先查詢,已經廢棄2中的深度查詢了