1. 基本概念
@classmethod 是 Python 中用于定義類方法的一種裝飾器。類方法與常規的實例方法不同,它的第一個參數是 cls,表示類本身,而不是實例。
class MyClass:class_attr = "Class Attribute"@classmethoddef class_method(cls):print(f"Accessing {cls.class_attr} via class method.")# 調用類方法(無需實例化)
MyClass.class_method() # 輸出: Accessing Class Attribute via class method.
2. classmethod vs staticmethod vs 實例方法
3. classmethod 的優點
3.1 封裝構造邏輯
將展開成對象的邏輯隔離在 class 內部,外部不需知道細節:
class Person:def __init__(self, name, age):self.name = nameself.age = age@classmethoddef from_string(cls, data_str):name, age = data_str.split(',')return cls(name, int(age))p = Person.from_string("Alice,30")
print(p.name, p.age) # 輸出: Alice 30
3.2 類狀態管理
修改類屬性或跨實例共享狀態。
class MyClass:class_var = 0@classmethoddef my_class_method(cls, value):cls.class_var += value# 實例化前調用類方法
MyClass.my_class_method(10)a = MyClass()
b = MyClass()print(a.class_var) # 10
print(b.class_var) # 10# 修改類屬性
MyClass.my_class_method(5)print(a.class_var) # 15
print(b.class_var) # 15# 給 a 實例設置同名屬性
a.class_var = 100print(a.class_var) # 100 -> 實例屬性覆蓋類屬性
print(b.class_var) # 15 -> 還是引用類屬性
print(MyClass.class_var) # 15
class_var 是類屬性,屬于類。
如果實例中沒有 class_var,訪問 obj.class_var 會去類中找。
一旦你給實例賦了 obj.class_var = 100,這個屬性就變成了實例屬性,不再和類屬性同步。
3.3 易于維護
如果構造函數變了參數,只需修改 classmethod,外部使用不用改。
3.4 多樣化構造方法
@classmethod
def from_dict(cls, d): ...@classmethod
def from_json(cls, j): ...
4. 子類是否需要重寫 classmethod
需要:子類構造參數與父類不同、子類邏輯與父類不同
可以不寫:父類方法已符合
5. classmethod + 多態封裝
通過 @classmethod 實現多態,不同子類可自定義類方法行為。
父類定義類方法接口,子類重寫實現多態。
調用時通過 cls 動態綁定到子類,避免硬編碼類名。
class Animal:@classmethoddef make_sound(cls):raise NotImplementedError("Subclasses must implement this!")class Dog(Animal):@classmethoddef make_sound(cls):return "Woof!"class Cat(Animal):@classmethoddef make_sound(cls):return "Meow!"def animal_sound(animal_cls):print(animal_cls.make_sound())animal_sound(Dog) # 輸出: Woof!
animal_sound(Cat) # 輸出: Meow!