[Python基礎]裝飾器classmethod定義類別方法

2024/01/25閱讀時間約 7 分鐘

在使用類別創建實例時,輸入的屬性的都要定義好資料型態,例如dog_1 = Dog("Buddy", 3),有沒有輸入一段字串讓他自己判斷的方法阿?

有的就是使用classmethod:

classmethod 是一種裝飾器,它用於定義類別方法。類別方法與實例方法不同,它們被綁定到類別而不是實例。通常,類別方法的第一個參數是 cls(代表類別本身),而不是 self

語法

class MyClass:
class_variable = "class_var"

@classmethod
def class_method(cls, arg1, arg2):
# 可以使用 cls 訪問類別變數
print(cls.class_variable)
# 其他邏輯...

使用方式:

# 通過類別調用
MyClass.class_method(arg1, arg2)
# 通過實例調用也可,但通常建議使用類別調用
my_instance = MyClass()
my_instance.class_method(arg1, arg2)

程式範例

通過類別調用類別方法

Dog 類別直接調用了類別方法 display_total_dogs,並顯示了總共創建了多少個 Dog 實例

class Dog:
total_dogs = 0

def __init__(self, name):
self.name = name
Dog.total_dogs += 1

@classmethod
def display_total_dogs(cls):
# cls 代表類別本身
print(f"Total dogs: {cls.total_dogs}")

# 創建幾個 Dog 的實例
dog1 = Dog("Buddy")
dog2 = Dog("Charlie")

# 通過類別調用類別方法
Dog.display_total_dogs() # 輸出: Total dogs: 2

直接從一個字符串創建 Dog 實例

統一創建實例: 使用 @classmethod 可以將相關的創建邏輯放在類別中,使得所有創建實例的方法都可以統一管理。這樣有利於程式碼的組織和維護。

直接輸入一段字串"Charlie,5"就可以創建一個實例,創建的程式邏輯都由類別方法來決定。

class Dog:
total_dogs = 0

def __init__(self, name, age):
self.name = name
self.age = age
Dog.total_dogs += 1

@classmethod
def create_from_string(cls, dog_string):
name, age = dog_string.split(",")
# 使用類別方法創建實例
return cls(name, int(age))

def display_info(self):
print(f"{self.name} is {self.age} years old.")

# 使用 __init__ 創建 Dog 實例
dog1 = Dog("Buddy", 3)
dog1.display_info() # 輸出: Buddy is 3 years old.

# 使用 @classmethod 創建 Dog 實例
dog_from_string = Dog.create_from_string("Charlie,5")
dog_from_string.display_info() # 輸出: Charlie is 5 years old.

# 顯示總共創建了多少個 Dog 實例
print(Dog.total_dogs) # 輸出: 2

這樣會想,那我使用__init__的方式來創建實例不就好了,但如果是要創建的物件屬性更複雜的話呢?

我們稍微來增加一下判斷的邏輯,若超過10歲我們就定義狀態為老狗,小於10歲就是年輕的狗。

若用__init__的方式來創建,我還要先定義好狀態是'年輕的',但使用 @classmethod的方式,跟上一個範例一樣是同個字串,讓類別方法根據程式邏輯自己判斷,這樣使用上是不是感覺更靈活了呢。

class Dog:
total_dogs = 0

def __init__(self, name, age, state):
self.name = name
self.age = age
self.state = state
Dog.total_dogs += 1

@classmethod
def create_from_string(cls, dog_string):
name, age_str = dog_string.split(",")

# 在創建實例之前,可以進行更複雜的處理,例如處理年齡字符串
age = int(age_str.strip())

# 如果年齡超過10歲,就將年齡設為10歲
state = '老' if age > 10 else '年輕的'

# 使用類別方法創建實例
return cls(name, age, state)

def display_info(self):
print(f"{self.name} 已經 {self.age} 歲,是{self.state}狗")

# 使用 __init__ 創建 Dog 實例
dog1 = Dog("Buddy", 3 ,'年輕的')
dog1.display_info() # 輸出: Buddy 已經 3 歲,是年輕的狗

# 使用 @classmethod 創建 Dog 實例
dog_from_string = Dog.create_from_string("Charlie, 15 ")
dog_from_string.display_info() # 輸出: Charlie 已經 15 歲,是老狗

# 顯示總共創建了多少個 Dog 實例
print(Dog.total_dogs) # 輸出: 2

@classmethod 提供了一個在整個類別中共享邏輯和更靈活的實例創建方式的機制,使得類別更具有彈性和可擴展性。


有機會在來談論比較複雜的案例,先把觀念搞清楚比較重要






49會員
88內容數
Python程式設計師,不是在學習就是在學習的路上
留言0
查看全部
發表第一個留言支持創作者!