python面向對象的知識梳理

面向對象(Object Oriented Programming

三個基本特徵:

1.封裝:包含兩個概念,對象將變量(狀態)和方法(用來改變狀態或執行涉及狀態的計算)集中在一個地方—即對象自己。設計模式

經過封裝隱藏類的內部數據,以免客戶端(client)代碼(即類外部的代碼)直接進行訪問。函數

2.繼承:在建立類時,該類也能夠從另外一個類那裏繼承方法和變量。被繼承的類,稱爲父類(parent class);繼承的類則被稱爲子類(child class)spa

3.多態:爲不一樣的基礎形態(數據類型)提供相關接口的能力。(其中接口指的就是函數或者方法)設計

變量:

類變量:屬於類對象及其建立的對象。code

實例變量:實例變量屬於對象。對象

定義屬性或方法時,在 屬性名或者方法名前 增長 兩個下劃線,定義的就是 私有 屬性或方法blog

其中在類中的方法能夠調用私有方法和變量繼承

可是子類不能訪問父類的私有方法及私有變量接口

class Dog(object):
    def __init__(self, name, age):
        self.name = name
        self.__age = age

    def eat(self):
        print('eating',self.__age)
        self.__eating_food()

    def __eating_food(self):
        print("food", self.name)


if __name__ == '__main__':
    d = Dog("tom", 15)# eating 15
    d.eat()# food tom

  

可是Python 中,並無 真正意義 的 私有

給 屬性、方法 命名時,實際是對 名稱 作了一些特殊處理,使得外界沒法訪問到處理方式:在 名稱 前面加上 _類名 => _類名__名稱(例如d_Dog_age)

單例模式

設計模式

  • 設計模式前人工做的總結和提煉,一般,被人們普遍流傳的設計模式都是針對 某一特定問題 的成熟的解決方案
  • 使用 設計模式 是爲了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性

 

單例設計模式

  • 目的 —— 讓 建立的對象,在系統中 只有 惟一的一個實例
  • 每一次執行 類名() 返回的對象,內存地址是相同的

__new__ 方法

  • 使用 類名() 建立對象時,Python 的解釋器 首先 會 調用 __new__ 方法爲對象 分配空間
  • __new__ 是一個 由 object 基類提供的 內置的靜態方法,主要做用有兩個:
    • 1) 在內存中爲對象 分配空間
    • 2) 返回 對象的引用
  • Python 的解釋器得到對象的 引用 後,將引用做爲 第一個參數,傳遞給 __init__ 方法

重寫 __new__ 方法 的代碼很是固定!內存

  • 重寫 __new__ 方法 必定要 return super().__new__(cls)
  • 不然 Python 的解釋器 得不到 分配了空間的 對象引用就不會調用對象的初始化方法
  • 注意:__new__ 是一個靜態方法,在調用時須要 主動傳遞 cls 參數

Python 中的單例

  • 單例 —— 讓 建立的對象,在系統中 只有 惟一的一個實例
    1. 定義一個 類屬性,初始值是 None,用於記錄 單例對象的引用
    2. 重寫 __new__ 方法
    3. 若是 類屬性 is None,調用父類方法分配空間,並在類屬性中記錄結果
    4. 返回 類屬性 中記錄的 對象引用

  

只執行一次初始化工做

  • 在每次使用 類名() 建立對象時,Python 的解釋器都會自動調用兩個方法:
    • __new__ 分配空間
    • __init__ 對象初始化
  • 在上一小節對 __new__ 方法改造以後,每次都會獲得 第一次被建立對象的引用
  • 可是:初始化方法還會被再次調用

需求

  • 初始化動做 只被 執行一次

解決辦法

  1. 定義一個類屬性 init_flag 標記是否 執行過初始化動做,初始值爲 False
  2. __init__ 方法中,判斷 init_flag,若是爲 False 就執行初始化動做
  3. 而後將 init_flag 設置爲 True
  4. 這樣,再次 自動 調用 __init__ 方法時,初始化動做就不會被再次執行
    class MusicPlayer(object):
    
        # 記錄第一個被建立對象的引用
        instance = None
        # 記錄是否執行過初始化動做
        init_flag = False
    
        def __new__(cls, *args, **kwargs):
    
            # 1. 判斷類屬性是不是空對象
            if cls.instance is None:
                # 2. 調用父類的方法,爲第一個對象分配空間,第一次調用父類方法返回的結果用cls.instance這個變量保存
                cls.instance = super().__new__(cls)
    
            # 3. 返回類屬性保存的對象引用(能夠理解爲第一次爲對象分配的內存地址)
            return cls.instance
    
        def __init__(self):
    
            if not MusicPlayer.init_flag:
                print("初始化音樂播放器")
    
                MusicPlayer.init_flag = True
    
    
    # 建立多個對象
    player1 = MusicPlayer()
    print(player1)
    
    player2 = MusicPlayer()
    print(player2)
相關文章
相關標籤/搜索