1. 程式人生 > >Python 面向對象的進階

Python 面向對象的進階

== name 位置 gif 技術分享 close 結果 主機 func

類的成員

類的成員可以分為三大類 : 字段 , 方法 和 屬性

技術分享圖片

註 : 所有的成員中,只有普通字段的內容保存對象中, 即 : 根據此類創建了對象,在內存就有多少個普通字段. 而其他的成員,則都是保存在類中 , 即 : 無論對象的多少,在內存中只創建一份.

一 , 字段

字段包括 : 普通字段和靜態字段,他們在定義和使用中有所區別,而最本質的區別是內存中保存的位置不同.

  •   普通字段屬於對象
  •   靜態字段屬於
技術分享圖片
 1 class Province:
 2     """
 3     字段的定義和使用
 4     """
 5     # 靜態字段
 6     country = "中國"
 7     def __init__(self,name):
 8 
 9         # 普通字段
10         self.name = name
11 
12 # 直接訪問普通字段
13 obj = Province("和順")
14 print(obj.name)
15 
16 # 直接訪問靜態字段
17 print(Province.country)
字段的定義和使用

有上述代碼可以看出 [普通字段需要通過對象來訪問] [靜態字段通過類訪問] , 在使用上可以看出普通字段和靜態字段的歸屬是不同的,其在內容的存儲方式類似如下圖:

技術分享圖片

右上圖可知:

  •   靜態字段在內存中只存一份
  •   普通字段在每個對象中都要保存一份

應用場景 : 通過類創建對象時 , 如果每個對象都具有相同的字段,那麽就使用靜態字段

二 方法

方法包括 : 普通方法 , 靜態方法 , 和 類方法 , 三種方法在內存中都歸屬類 , 區別在於調用方式不同

  •   普通方法 : 由對象調用 ; 至少一個self
    參數; 執行普通方法時 , 自動將調用該方法的對象賦值給 self;
  •   類方法 : 由調用 ; 至少一個cls 參數 ; 執行類方法時 , 自動將調用該方法的賦值給cls;
  •   靜態方法 : 由調用 ; 無默認參數;
技術分享圖片
 1 class Foo:
 2 
 3     def __init__(self,name):
 4         self.name = name
 5 
 6     def ord_func(self):
 7         ‘‘‘
 8         定義一個普通方法,至少有一個self參數
 9         ‘‘‘
10         print(self.name)
11         print("普通方法")
12 
13     @classmethod
14     def class_func(cls):
15         ‘‘‘
16         定義一個類方法,至少有一個cls參數
17         ‘‘‘
18         print("類方法")
19 
20     @staticmethod
21     def static_func():
22         """
23         定義一個靜態類方法, 無需默認參數
24         """
25         print("靜態類方法")
26 
27 # 調用普通方法
28 f = Foo("和順")
29 f.ord_func()
30 
31 # 調用類方法
32 Foo.class_func()
33 
34 # 調用靜態類方法
35 Foo.static_func()
方法的定義和使用

技術分享圖片

相同點 : 對於所有的方法而言 , 均屬於類(非對象) 中 , 所以 , 在內存中也只保存一份.

不同點 : 方法調用者不同 , 調用方法時自動轉入的參數不同

三 屬 性

如果你已經了解Python類中的方法 , 那麽屬性就非常簡單了 , 因為Python中的屬性其實是普通方法的變種

對於屬性 ,有三個知識點

  •   屬性的基本使用
  •   屬性的兩種定義方式

1 , 屬性的基本使用

技術分享圖片
 1 class Foo:
 2 
 3     def func(self):
 4         pass
 5     # 定義屬性
 6     @property
 7     def prop(self):
 8         pass
 9 
10 foo_obj = Foo()
11 foo_obj.func()
12 foo_obj.prop  # 調用屬性  
屬性的定義和是使用

技術分享圖片

由屬性的定義和調用要註意一下幾點:

  •   定義時 , 在普通方法的基礎上添加 @property 裝飾器 ;
  •   定義時 , 屬性僅有一個self 參數
  •   調用時 , 無需括號

      方法 : foo_obj.func()

      屬性 : foo_obj.prop

註意 : 屬性存在意義是 : 訪問屬性是可以制造出和訪問字段完全相同的假象

    屬性由方法變種而來 , 如果Python中沒有屬性 , 方法完全可以代替其功能

實例 : 對於主機列表頁面, 每次請求不可能把數據庫中的所有內容都顯示帶頁面上 , 而是通過分頁的功能局部顯示, 所以在向數據庫中請求數據時要顯示的指定獲取從第M條到第N條的所有數據 (即 : limit m, n) , 這個分頁的功能包括 :

  •    根據用戶請求的當前頁總數據條數計算出 M 和 N
  •    根據 M 和 N 去數據庫中請求數據

技術分享圖片
 1 class Pagenation:
 2     ‘‘‘
 3     分頁處理代碼
 4     ‘‘‘
 5     def __init__(self,data_list, page,per_page_num = 10):
 6         ‘‘‘
 7        初始化
 8         :param data_list: 所有數據
 9         :param page: 第幾頁
10         :param per_page_num:  每頁顯示幾條數據
11         ‘‘‘
12         self.data_list = data_list
13         self.page = page
14         self.per_page_num = per_page_num
15     @property
16     def start(self):
17         """
18         計算起始頁
19         :return:
20         """
21         return (self.page - 1) * self.per_page_num
22     @property
23     def end(self):
24         """
25         計算結尾頁
26         :return:
27         """
28         return self.page * self.per_page_num
29 
30     def show(self):
31         """
32         打印當前頁面
33         :return: 
34         """
35         ret = self.data_list[self.start:self.end]
36         for i in ret :
37             print(i)
38 
39 
40 data_list = []
41 for i in range(1,10001):
42     data_list.append("皇家%s號" % i)
43 # obj = Pagenation(data_list)
44 while True:
45     page = int(input("請輸入你查看的頁數:"))
46     obj = Pagenation(data_list,page)
47     obj.show()
打印頁面

從上述可見 , Python的屬性的功能是: 屬性內部進行一系列的邏輯計算 , 最終將計算結果返回

屬性的兩種定義方式

  •   裝飾器 即 : 再方法上應用裝飾器
  •   靜態字段 即 : 在類中定義值為property 對象的靜態字

裝飾器方式:在類的普通方法上應用@property裝飾器

類成員的修飾符

類的所有成員在上一步驟中已經做了詳細的介紹 , 對於每一個類的成員而言都有兩種形式:

  •   公有成員 , 在任何地方都能訪問
  •   私有成員 , 只有在類的內部才能訪問

私有成員和公有成員的定義不同 : 私有成員命名時, 前兩個字符是下劃線 . (特殊成員除外 , 例如: __init__ , __call__ , __dict __ 等)

1 class C:
2 
3     def __init__(self):
4         self.name = "公有字段"
5         self.__foo = "私有字段"

私有成員和公有成員的訪問限制不同 :

靜態字段

  •   公有靜態字段 : 類可以訪問; 類內部可以訪問 , 派生類中可以訪問
  •   私有靜態字段 : 僅類內部可以訪問
技術分享圖片
 1 class C:
 2 
 3     name = "公有靜態字段"
 4 
 5     def func(self):
 6         print C.name
 7 
 8 class D(C):
 9 
10     def show(self):
11         print C.name
12 
13 
14 C.name         # 類訪問
15 
16 obj = C()
17 obj.func()     # 類內部可以訪問
18 
19 obj_son = D()
20 obj_son.show() # 派生類中可以訪問
公有靜態字段 技術分享圖片
 1 class C:
 2 
 3     __name = "公有靜態字段"
 4 
 5     def func(self):
 6         print C.__name
 7 
 8 class D(C):
 9 
10     def show(self):
11         print C.__name
12 
13 
14 C.__name       # 類訪問            ==> 錯誤
15 
16 obj = C()
17 obj.func()     # 類內部可以訪問     ==> 正確
18 
19 obj_son = D()
20 obj_son.show() # 派生類中可以訪問   ==> 錯誤
私有靜態字段

普通字段

  •   公有普通字段 : 對象可以訪問 ; 類內部可以訪問 ; 派生類中可以訪問
  •   私有普通字段 : 僅類內部可訪問 ;

ps : 如果想要強制訪問私有字段 , 可以通過 [對象.__類名__私有字段段名] 訪問 ( 如: obj.__C__foo) , 不建議強制訪問私有成員 .

技術分享圖片
 1 class C:
 2     
 3     def __init__(self):
 4         self.foo = "公有字段"
 5 
 6     def func(self):
 7         print self.foo  # 類內部訪問
 8 
 9 class D(C):
10     
11     def show(self):
12         print self.foo # 派生類中訪問
13 
14 obj = C()
15 
16 obj.foo     # 通過對象訪問
17 obj.func()  # 類內部訪問
18 
19 obj_son = D();
20 obj_son.show()  # 派生類中訪問
公有字段 技術分享圖片
 1 class C:
 2     
 3     def __init__(self):
 4         self.__foo = "私有字段"
 5 
 6     def func(self):
 7         print self.foo  # 類內部訪問
 8 
 9 class D(C):
10     
11     def show(self):
12         print self.foo # 派生類中訪問
13 
14 obj = C()
15 
16 obj.__foo     # 通過對象訪問    ==> 錯誤
17 obj.func()  # 類內部訪問        ==> 正確
18 
19 obj_son = D();
20 obj_son.show()  # 派生類中訪問  ==> 錯誤
私有字段

方法 , 屬性 的訪問 和上述的方式相似 , 即私有成員只能在類的內部使用

ps : 非要訪問私有屬性的話 , 可以通過 對象.__類__屬性名

Python 面向對象的進階