8_09_類屬性和類方法

目標

  • 類的結構
  • 類屬性和實例屬性
  • 類方法和靜態方法

01. 類的結構

1.1 術語 —— 實例

  1. 使用面相對象開發,第 1 步 是設計
  2. 使用 類名() 創建對象,創建對象 的動作有兩步:
    -1) 在內存中爲對象 分配空間
    -2) 調用初始化方法 __init__ 爲 對象初始化
  3. 對象創建後,內存 中就有了一個對象的 實實在在 的存在 —— 實例

在這裏插入圖片描述
因此,通常也會把:

  1. 創建出來的 對象 叫做 實例
  2. 創建對象的 動作 叫做 實例化
  3. 對象的屬性 叫做 實例屬性
  4. 對象調用的方法 叫做 實例方法

在程序執行時:

  1. 對象各自擁有自己的 實例屬性
  2. 調用對象方法,可以通過 self.
    – 訪問自己的屬性
    – 調用自己的方法

結論

  • 每一個對象 都有自己 獨立的內存空間,保存各自不同的屬性
  • 多個對象的方法,在內存中只有一份,在調用方法時,需要把對象的引用 傳遞到方法內部

1.2 類是一個特殊的對象

Python 中 一切皆對象:

  • class AAA: 定義的類屬於 類對象
  • obj1 = AAA() 屬於 實例對象
  • 在程序運行時, 同樣 會被加載到內存
  • Python 中, 是一個特殊的對象 —— 類對象
  • 在程序運行時,類對象 在內存中 只有一份,使用 一個類 可以創建出 很多個對象實例
  • 除了封裝 實例屬性方法外,類對象 還可以擁有自己的 屬性方法
    • 類屬性
    • 類方法
  • 通過 類名. 的方式可以 訪問類的屬性 或者 調用類的方法

在這裏插入圖片描述

02. 類屬性和實例屬性

2.1 概念和使用

  • 類屬性 就是給 類對象 中定義的 屬性
  • 通常用來記錄 與這個類相關 的特徵
  • 類屬性 不會用於記錄 具體對象的特徵

示例需求

  • 定義一個 工具類
  • 每件工具都有自己的 name
  • 需求 —— 知道使用這個類,創建了多少個工具對象?

在這裏插入圖片描述

class Tool(object):

    # 使用賦值語句,定義類屬性,記錄創建工具對象的總數
    count = 0

    def __init__(self, name):
        self.name = name

        # 針對類屬性做一個計數+1
        Tool.count += 1


# 創建工具對象
tool1 = Tool("斧頭")
tool2 = Tool("榔頭")
tool3 = Tool("鐵鍬")

# 知道使用 Tool 類到底創建了多少個對象?
print("現在創建了 %d 個工具" % Tool.count)

2.2 屬性的獲取機制(科普)

  • Python屬性的獲取 存在一個 向上查找機制

在這裏插入圖片描述

  • 因此,要訪問類屬性有兩種方式:
    • 類名.類屬性
    • 對象.類屬性 (不推薦)

注意

  • 如果使用 對象.類屬性 = 值 賦值語句,只會 給對象添加一個屬性,而不會影響到 類屬性的值

03. 類方法和靜態方法

3.1 類方法

  • 類屬性 就是針對 類對象 定義的屬性

    • 使用 賦值語句class 關鍵字下方可以定義 類屬性
    • 類屬性 用於記錄 與這個類相關 的特徵
  • 類方法 就是針對 類對象 定義的方法

    • 類方法 內部可以直接訪問 類屬性 或者調用其他的 類方法

語法如下

@classmethod
def 類方法名(cls):
    pass
  • 類方法需要用 修飾器 @classmethod 來標識,告訴解釋器這是一個類方法
  • 類方法的 第一個參數 應該是 cls
    • 哪一個類 調用的方法,方法內的 cls 就是 哪一個類的引用
    • 這個參數和 實例方法 的第一個參數是 self 類似
    • 提示 使用其他名稱也可以,不過習慣使用 cls
  • 通過 類名. 調用 類方法調用方法時,不需要傳遞 cls 參數
  • 在方法內部
    • 可以通過 cls. 訪問類的屬性
    • 也可以通過 cls. 調用其他的類方法

示例需求

  • 定義一個 工具類
  • 每件工具都有自己的 name
  • 需求 —— 在 封裝一個 show_tool_count 的類方法,輸出使用當前這個類,創建的對象個數

在這裏插入圖片描述

@classmethod
def show_tool_count(cls):
    """顯示工具對象的總數"""
    print("工具對象的總數 %d" % cls.count)

在類方法內部,可以直接使用 cls 訪問 類屬性 或者 調用類方法

3.2 靜態方法

  • 在開發時,如果需要在 中封裝一個方法,這個方法:

    • 不需要 訪問 實例屬性 或者調用 實例方法
    • 不需要 訪問 類屬性 或者調用 類方法
  • 這個時候,可以把這個方法封裝成一個 靜態方法

語法如下

@staticmethod
def 靜態方法名():
    pass
  • 靜態方法 需要用 修飾器 @staticmethod 來標識,告訴解釋器這是一個靜態方法
  • 通過 類名. 調用 靜態方法
class Dog(object):
    
    # 狗對象計數
    dog_count = 0
    
    @staticmethod
    def run():
        
        # 不需要訪問實例屬性也不需要訪問類屬性的方法
        print("狗在跑...")

    def __init__(self, name):
        self.name = name

3.3 方法綜合案例

需求

  1. 設計一個 Game
  2. 屬性:
    • 定義一個 類屬性 top_score 記錄遊戲的 歷史最高分
    • 定義一個 實例屬性 player_name 記錄 當前遊戲的玩家姓名
  3. 方法:
    • 靜態方法 show_help 顯示遊戲幫助信息
    • 類方法 show_top_score 顯示歷史最高分
    • 實例方法 start_game 開始當前玩家的遊戲
  4. 主程序步驟
    • 查看幫助信息
    • 查看歷史最高分
    • 創建遊戲對象,開始遊戲

在這裏插入圖片描述
案例小結

  1. 實例方法 —— 方法內部需要訪問 實例屬性
    實例方法 內部可以使用 類名. 訪問類屬性
  2. 類方法 —— 方法內部 需要訪問 類屬性
  3. 靜態方法 —— 方法內部,不需要訪問 實例屬性類屬性

注意:如果方法內部 即需要訪問 實例屬性,又需要訪問 類屬性,應該定義成實例方法,因爲,類只有一個,在 實例方法 內部可以使用 類名. 訪問類屬性

class Game(object):

    # 遊戲最高分,類屬性
    top_score = 0

    @staticmethod
    def show_help():
        print("幫助信息:讓殭屍走進房間")
        
    @classmethod
    def show_top_score(cls):
        print("遊戲最高分是 %d" % cls.top_score)

    def __init__(self, player_name):
        self.player_name = player_name

    def start_game(self):
        print("[%s] 開始遊戲..." % self.player_name)
        
        # 使用類名.修改歷史最高分
        Game.top_score = 999

# 1. 查看遊戲幫助
Game.show_help()

# 2. 查看遊戲最高分
Game.show_top_score()

# 3. 創建遊戲對象,開始遊戲
game = Game("小明")

game.start_game()

# 4. 遊戲結束,查看遊戲最高分
Game.show_top_score()

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章