@classmethod
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!