天天看點

類屬性和類方法

目錄

目标

01. 類的結構

1.1 術語 —— 執行個體

1.2 類是一個特殊的對象

02. 類屬性和執行個體屬性

2.1 概念和使用

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

03. 類方法和靜态方法

3.1 類方法

3.2 靜态方法

3.3 方法綜合案例

  • 類的結構
  • 類屬性和執行個體屬性
  • 類方法和靜态方法

  1. 使用面相對象開發,第 1 步 是設計 類
  2. 使用 類名() 建立對象,建立對象 的動作有兩步:
    • 1) 在記憶體中為對象 配置設定空間
    • 2) 調用初始化方法 

      __init__

       為 對象初始化
  3. 對象建立後,記憶體 中就有了一個對象的 實實在在 的存在 —— 執行個體

類屬性和類方法

是以,通常也會把:

  1. 建立出來的 對象 叫做 類 的 執行個體
  2. 建立對象的 動作 叫做 執行個體化
  3. 對象的屬性 叫做 執行個體屬性
  4. 對象調用的方法 叫做 執行個體方法

在程式執行時:

  1. 對象各自擁有自己的 執行個體屬性
  2. 調用對象方法,可以通過 

    self.

    • 通路自己的屬性
    • 調用自己的方法

結論

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

Python

 中 一切皆對象:
  • class AAA:

     定義的類屬于 類對象
  • obj1 = AAA()

     屬于 執行個體對象
  • 在程式運作時,類 同樣 會被加載到記憶體
  • 在 

    Python

     中,類 是一個特殊的對象 —— 類對象
  • 在程式運作時,類對象 在記憶體中 隻有一份,使用 一個類 可以建立出 很多個對象執行個體
  • 除了封裝 執行個體 的 屬性 和 方法外,類對象 還可以擁有自己的 屬性 和 方法
    1. 類屬性
    2. 類方法
  • 通過 類名. 的方式可以 通路類的屬性 或者 調用類的方法
類屬性和類方法
類屬性和類方法

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

示例需求

  • 定義一個 工具類
  • 每件工具都有自己的 

    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)

           

  • Python

     中 屬性的擷取 存在一個 向上查找機制
類屬性和類方法
  • 是以,要通路類屬性有兩種方式:
    1. 類名.類屬性
    2. 對象.類屬性 (不推薦)

注意

  • 如果使用 

    對象.類屬性 = 值

     指派語句,隻會 給對象添加一個屬性,而不會影響到 類屬性的值
class Tool(object):

    # 使用指派語句定義類屬性,記錄所有工具對象的數量
    count = 0

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

        # 讓類屬性的值+1
        Tool.count += 1


# 1. 建立工具對象
tool1 = Tool("斧頭")
tool2 = Tool("榔頭")
tool3 = Tool("水桶")

# 2. 輸出工具對象的總數
# print(Tool.count)
print("工具對象總數 %d" % tool3.count)
           
class Tool(object):

    # 使用指派語句定義類屬性,記錄所有工具對象的數量
    count = 0

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

        # 讓類屬性的值+1
        Tool.count += 1


# 1. 建立工具對象
tool1 = Tool("斧頭")
tool2 = Tool("榔頭")
tool3 = Tool("水桶")

# 2. 輸出工具對象的總數
tool3.count = 99
print("工具對象總數 %d" % tool3.count)
print("===> %d" % Tool.count)
           
類屬性和類方法

通過對象的方式通路類屬性時,讀可以,但指派會有點不一樣:隻會從對象中對比有無屬性,沒有就建立一個,而不會向上查找類的屬性了。

  • 類屬性 就是針對 類對象 定義的屬性
    • 使用 指派語句 在 

      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

 通路 類屬性 或者 調用類方法

  • 在開發時,如果需要在 類 中封裝一個方法,這個方法:
    • 既 不需要 通路 執行個體屬性 或者調用 執行個體方法
    • 也 不需要 通路 類屬性 或者調用 類方法
  • 這個時候,可以把這個方法封裝成一個 靜态方法
@staticmethod
def 靜态方法名():
    pass
           
  • 靜态方法 需要用 修飾器 

    @staticmethod

     來辨別,告訴解釋器這是一個靜态方法
  • 通過 類名. 調用 靜态方法
class Dog(object):
    
    # 狗對象計數
    dog_count = 0
    
    @staticmethod
    def run():
        
        # 不需要通路執行個體屬性也不需要通路類屬性的方法
        print("狗在跑...")

    def __init__(self, name):
        self.name = name
        
           
class Tool(object):

    # 使用指派語句定義類屬性,記錄所有工具對象的數量
    count = 0

    @classmethod
    def show_tool_count(cls):

        print("工具對象的數量 %d" % cls.count)

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

        # 讓類屬性的值+1
        Tool.count += 1


# 建立工具對象
tool1 = Tool("斧頭")
tool2 = Tool("榔頭")

# 調用類方法
Tool.show_tool_count()
           
class Dog(object):

    @staticmethod
    def run():
        
        # 不通路執行個體屬性/類屬性
        print("小狗要跑...")

# 通過類名.調用靜态方法 - 不需要建立對象
Dog.run()
           

需求

  1. 設計一個 

    Game

     類
  2. 屬性:
    • 定義一個 類屬性 

      top_score

       記錄遊戲的 曆史最高分
    • 定義一個 執行個體屬性 

      player_name

       記錄 目前遊戲的玩家姓名
  3. 方法:
    • 靜态方法 

      show_help

       顯示遊戲幫助資訊
    • 類方法 

      show_top_score

       顯示曆史最高分
    • 執行個體方法 

      start_game

       開始目前玩家的遊戲
  4. 主程式步驟
    • 1) 檢視幫助資訊
    • 2) 檢視曆史最高分
    • 3) 建立遊戲對象,開始遊戲
類屬性和類方法

案例小結

  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()

​