Skip to main content
Documents
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Decorator -- classmethod

🚀 1. classmethod 是什么?

@classmethod 用来把类中的方法标记为 类方法:

  • 会自动接收 cls(类本身),而不是实例
  • 适合处理“全局于类”的逻辑
  • 常用于工厂方法、配置方法、批量创建对象等

示例:

class Demo:
    @classmethod
    def show(cls):
        print(cls)

调用:

Demo.show()  # <class '__main__.Demo'>
Demo().show()  # <class '__main__.Demo'>

📌 2. 与 staticmethod 和普通方法对比(最重要的部分)

方法类型 自动接收参数 典型用途
普通方法 (def method(self)) self(实例) 操作实例数据
类方法 (@classmethod) cls(类) 工厂方法、创建实例、访问类属性
静态方法 (@staticmethod) 工具函数,与类相关但不需要访问类或实例

📌 3. 最简单示例

class User:
    count = 0

    def __init__(self):
        User.count += 1

    @classmethod
    def get_count(cls):
        return cls.count

使用:

print(User.get_count())

📌 4. ✨ 最常用场景:工厂方法(强烈建议掌握)

你创建对象时,除了 __init__,还可能需要基于不同输入创建对象,这就是工厂方法的典型场景。

例如,把 JSON 字典变成对象:

class User:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    @classmethod
    def from_dict(cls, data: dict):
        return cls(data["name"], data["age"])

使用:

user = User.from_dict({"name": "jack", "age": 18})

📌 5. ✨ 允许子类自动继承正确的类(classmethod 最大意义)

class Animal:
    @classmethod
    def create(cls, name):
        return cls(name)   # 注意:这里返回的是 *子类* 的实例

class Dog(Animal):
    def __init__(self, name):
        self.name = name

d = Dog.create("旺财")
print(type(d))  # <class '__main__.Dog'>

若用 staticmethod,就无法自动返回子类实例。

📌 6. ✨ 配置加载器(FastAPI、你的项目都能用)

你项目可以这样写全局配置:

class AppConfig:
    ENV = "production"

    @classmethod
    def is_prod(cls):
        return cls.ENV == "production"

使用:

if AppConfig.is_prod():
    ...

📌 7. ✨ 数据库模型批量创建(你的 SQLAlchemy 场景)

class UserModel(Base):
    ...

    @classmethod
    def create_many(cls, session, items: list[dict]):
        objects = [cls(**item) for item in items]
        session.add_all(objects)
        session.commit()
        return objects

📌 8. ✨ 单例模式(高级用法)

class Singleton:
    _instance = None

    @classmethod
    def get_instance(cls):
        if cls._instance is None:
            cls._instance = cls()
        return cls._instance

📌 9. ✨ 作为“构造器”的增强版 init

你希望不同的输入格式创建对象:

class Date:
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day

    @classmethod
    def from_string(cls, s: str):
        y, m, d = map(int, s.split("-"))
        return cls(y, m, d)

使用:

d = Date.from_string("2025-06-21")

📌 10. 实现一个你项目可以直接用的工具类

你常用的 “stock coderename” 可以改成 classmethod,让用户可以扩展子类:

class StockCodeUtil:
    prefix_map = {
        "00": "sz",
        "60": "sh",
    }

    @classmethod
    def encode(cls, code: str):
        for k, v in cls.prefix_map.items():
            if code.startswith(k):
                return code.replace(k, v, 1)
        return code

    @classmethod
    def decode(cls, code: str):
        for k, v in cls.prefix_map.items():
            if code.startswith(v):
                return code.replace(v, k, 1)
        return code

📌 11. 什么时候应该使用 classmethod?

建议使用 classmethod 的场景:

  • 工厂函数
  • 需要访问类属性
  • 需要返回当前类或子类的实例
  • 单例模式
  • 批量创建对象
  • 数据转换(from_dict, from_json, from_xxx)
  • 环境配置、初始化逻辑

📌 12. 什么时候不应该使用 classmethod?

  • ❌ 当需要访问实例属性时(用 self)
  • ❌ 当方法完全和类无关时(用 staticmethod)

📌 13. 总结(最实用记忆法)

💡 使用规则:

  • 需要 self -> 普通方法
  • 需要 cls -> classmethod
  • 都不需要 -> staticmethod