1. 程式人生 > >Python的新式類和舊式類

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 全部程式碼
  1. 註釋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中的深度查詢了