python 面向對象


1、面向對象的基本知識

  • 面向對象是一種編程方式,此編程方式的實現是基於對   對象 的使用
  • 是一個模板,模板中包裝了多個函數供使用(可以講多函數中公用的變量封裝到對象中)
  • 對象,根據模板創建的實例(即:對象),實例用於調用被包裝在類中的函數
  • 面向對象三大特性:封裝、繼承和多態

2、類的成員

類的成員可以分為三大類:字段、方法和屬性(1、字段:普通字段、靜態字段;2、方法:普通方法、類方法、靜態方法;3、屬性:普通屬性)

 

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

 2.1、字段

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

  • 普通字段 屬於 對象
  • 靜態字段 屬於 
    class Province:
        # 靜態字段
        country ='中國'
        def __init__(self, name):
            # 普通字段
            self.name = name
    # 直接訪問普通字段
    obj = Province('河北省')
    print(obj.name)
    # 直接訪問靜態字段
    print(Province.country)
    print(obj.country)
    
  • 靜態字段在內存中只保存一份
  • 普通字段在每個對象中都要保存一份

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

 2.2、方法

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

  • 普通方法:由對象調用;至少一個self參數;執行普通方法時,自動將調用該方法的對象賦值給self
  • 類方法:由調用; 至少一個cls參數;執行類方法時,自動將調用該方法的復制給cls
  • 靜態方法:由調用;無默認參數;
class Foo:
    def __init__(self, name):
        self.name = name

    def ord_func(self):
        """ 定義普通方法,至少有一個self參數 """
        # print self.name
        print('普通方法')

    @classmethod
    def class_func(cls):
        """ 定義類方法,至少有一個cls參數 """
        print('類方法')

    @staticmethod
    def static_func():
        """ 定義靜態方法 ,無默認參數"""

        print('靜態方法')


# 調用普通方法
f = Foo(11)
f.ord_func()
# 調用類方法
Foo.class_func()
# 調用靜態方法
Foo.static_func()

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

不同點:方法調用者不同、調用方法時自動傳入的參數不同。

2.3、屬性

Python中的屬性其實是普通方法的變種。 

2.3.1、屬性的基本使用

 由屬性的定義和調用要注意以下幾點:

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

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

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

class Foo:

    def func(self):
        pass

    # 定義屬性
    @property
    def prop(self):
        pass

foo_obj = Foo()

foo_obj.func()
foo_obj.prop   #調用屬性  

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

  • 根據用戶請求的當前頁和總數據條數計算出 m n
  • 根據m n 去數據庫中請求數據 
class Pages:
    def __init__(self, current_page):
        # 用戶當前請求的頁碼(第一頁、第二頁...)
        self.current_page = current_page
        # 每頁默認顯示10條數據
        self.per_items = 10
    @property
    def start(self):
        val = (self.current_page - 1) * self.per_items
        return val

    @property
    def end(self):
        val = self.current_page * self.per_items
        return val
p = Pages(2)
print(p.start)
print(p.end) 

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

2.3.2、屬性的兩種定義方式

屬性的定義有兩種方式:

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

裝飾器方法:

class Goods(object):

    def __init__(self):
        # 原價
        self.original_price = 100
        # 折扣
        self.discount = 0.8

    @property
    def price(self):
        # 實際價格 = 原價 * 折扣
        new_price = self.original_price * self.discount
        return new_price

    @price.setter
    def price(self, value):
        self.original_price = value

    @price.deleter
    def price(self, value):
        del self.original_price

 obj = Goods()
 print(obj.price)         # 獲取商品價格
 obj.price = 200   # 修改商品原價
 print(obj.price)
 del obj.price     # 刪除商品原價

 print(obj.price)  

靜態字段方法

class Foo:

    def get_bar(self):
        return 'Hello'

    BAR = property(get_bar)

obj = Foo()
reuslt = obj.BAR        # 自動調用get_bar方法,並獲取方法的返回值
print(reuslt) 

property的構造方法中有個四個參數

  • 第一個參數是方法名,調用 對象.屬性 時自動觸發執行方法
  • 第二個參數是方法名,調用 對象.屬性 = XXX 時自動觸發執行方法
  • 第三個參數是方法名,調用 del 對象.屬性 時自動觸發執行方法
  • 第四個參數是字符串,調用 對象.屬性.__doc__ ,此參數是該屬性的描述信息

由於靜態字段方式創建屬性具有三種訪問方式,我們可以根據他們幾個屬性的訪問特點,分別將三個方法定義為對同一個屬性:獲取、修改、刪除 

class Goods(object):

    def __init__(self):
        # 原價
        self.original_price = 100
        # 折扣
        self.discount = 0.8

    def get_price(self):
        # 實際價格 = 原價 * 折扣
        new_price = self.original_price * self.discount
        return new_price

    def set_price(self, value):
        self.original_price = value

    def del_price(self, value):
        del self.original_price

    PRICE = property(get_price, set_price, del_price, '價格屬性描述...')

obj = Goods()
obj.PRICE         # 獲取商品價格
obj.PRICE = 200   # 修改商品原價
del obj.PRICE     # 刪除商品原價

3、類成員的修飾符

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

  • 公有成員,在任何地方都能訪問(私有成員命名時,前兩個字符是下划線。)
  • 私有成員,只有在類的內部才能訪問。
class C:

    def __init__(self):
        self.name = "公有字段"
        self.__foo = "私有字段"

靜態字段

  • 公有靜態字段:類可以訪問;類內部可以訪問;派生類中可以訪問
  • 私有靜態字段:僅類內部可以訪問;

 

普通字段

 

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

 

ps:如果想要強制訪問私有字段,可以通過 【對象._類名__私有字段明 】訪問(如:obj._C__foo),不建議強制訪問私有成員。

class C:
    dic = "靜態公有字段"
    _iso = "靜態私有字段"
    def __init__(self):
        self.name = "公有字段"
        self.__foo = "私有字段"

    def func(self):
        print(self.__foo)    # 類內部訪問


class D(C):
    def show(self):
        print(self.__foo)   #派生類中訪問

obj = C()
print(obj._C__foo )         # 通過對象訪問
obj.func()                  # 類內部訪問
obj_son = D()
obj_son.show()              # 派生類中訪問

 

4、類的特殊成員 

  Python的類成員以及成員修飾符,從而了解到類中有字段、方法和屬性三大類成員,並且成員名前如果有兩個下划線,則表示該成員是私有成員,私有成員只能由類內部調用。無論人或事物往往都有不按套路出牌的情況,Python的類成員也是如此,存在着一些具有特殊含義的成員,詳情如下:

  1、 __doc__

    表示類的描述信息

 

 

  2、__module__  __class__ 

 

    __module__ 表示當前操作的對象在那個模塊

 

    __class__     表示當前操作的對象的類是什么

 

 

  3、 __init__

 

    構造方法,通過類創建對象時,自動觸發執行。

 

 

  4、 __del__

 

    析構方法,當對象在內存中被釋放時,自動觸發執行。

 

    注:此方法一般無須定義,因為Python是一門高級語言,程序員在使用時無需關心內存的分配和釋放,因為此工作都是交給Python解釋器來執行,所以,析構函數的調用

    是由解釋器在進行垃圾回收時自動觸發執行的。

 

 

  5、 __call__

 

    對象后面加括號,觸發執行。

 

    注:構造方法的執行是由創建對象觸發的,即:對象 = 類名() ;而對於 __call__ 方法的執行是由對象后加括號觸發的,即:對象() 或者 類()()

 

 

  6、__dict__

 

    類或對象中的所有成員

 

    上文中我們知道:類的普通字段屬於對象;類中的靜態字段和方法等屬於類,即:

 

 

   7. __str__

 

    如果一個類中定義了__str__方法,那么在打印 對象 時,默認輸出該方法的返回值。

 

 

  8__getitem____setitem____delitem__

 

    用於索引操作,如字典。以上分別表示獲取、設置、刪除數據

 

 

  9__getslice____setslice____delslice__

 

     該三個方法用於分片操作,如:列表

class Foo(object):
 
    def __getslice__(self, i, j):
        print('__getslice__',i,j)
 
    def __setslice__(self, i, j, sequence):
        print('__setslice__',i,j)
 
    def __delslice__(self, i, j):
        print('__delslice__',i,j)
 
obj = Foo()
 
obj[-1:1]                   # 自動觸發執行 __getslice__
obj[0:1] = [11,22,33,44]    # 自動觸發執行 __setslice__
del obj[0:2]                # 自動觸發執行 __delslice__

 

  

  10. __iter__ 

  用於迭代器,之所以列表、字典、元組可以進行for循環,是因為類型內部定義了 __iter__ 

 

  

  11. __new__  __metaclass__

 5、函數參數

函數參數說明:

  位置形參,星號元組形參,命名關鍵字形參,雙星號字典形參和缺省形參可以混合使用

函數參數前后順序:

  位置參數,星號元組參數,命名關鍵字形參,雙星號字典形參 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM