You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于装饰器DRY原则的疑问:如何避免重复使用@classmethod?

如何在Python中批量标记多个方法为类方法(避免重复使用@classmethod)

原代码报错原因

Python的装饰器是针对单个方法的语法糖,@classmethod仅会修饰紧跟在它下方的方法(即示例中的more_holiness)。后面的more_luck没有被装饰,本质还是普通实例方法:当通过类直接调用时,Python不会自动将类对象作为第一个参数传入(只有被@classmethod/@staticmethod修饰的方法才具备自动绑定逻辑),因此会提示缺少cls参数。

无需重复@classmethod的解决方案

方案1:自定义类装饰器批量转换

编写一个类装饰器,可指定目标方法名,或按命名规则自动将方法转为类方法:

指定方法名版本

def classmethods(*method_names):
    def decorator(cls):
        for name in method_names:
            method = getattr(cls, name)
            setattr(cls, name, classmethod(method))
        return cls
    return decorator

@classmethodethods('more_holiness', 'more_luck')
class Cat:
    holiness = 100
    luck = 100
    
    def more_holiness(cls):
        cls.holiness += 1

    def more_luck(cls):
        cls.luck += 1

Cat.more_holiness()
print(Cat.holiness)  # 输出101
Cat.more_luck()
print(Cat.luck)      # 输出101

按命名规则自动转换版本

如果想统一处理符合命名规则的方法(比如以more_开头),可以修改装饰器逻辑:

def auto_classmethods(prefix):
    def decorator(cls):
        for name, method in cls.__dict__.items():
            if callable(method) and name.startswith(prefix):
                setattr(cls, name, classmethod(method))
        return cls
    return decorator

@auto_classmethods('more_')
class Cat:
    holiness = 100
    luck = 100
    
    def more_holiness(cls):
        cls.holiness += 1

    def more_luck(cls):
        cls.luck += 1

方案2:使用元类批量处理

元类可以控制类的创建流程,在类定义完成后自动将指定方法转为类方法:

class ClassMethodMeta(type):
    def __new__(cls, name, bases, attrs):
        # 遍历类属性,将符合命名规则的方法转为类方法
        for attr_name, attr_value in attrs.items():
            if callable(attr_value) and attr_name.startswith('more_'):
                attrs[attr_name] = classmethod(attr_value)
        return super().__new__(cls, name, bases, attrs)

class Cat(metaclass=ClassMethodMeta):
    holiness = 100
    luck = 100
    
    def more_holiness(cls):
        cls.holiness += 1

    def more_luck(cls):
        cls.luck += 1

注意事项

  • 批量转换的方式虽然减少了重复代码,但可读性可能不如直接使用@classmethod直观,团队协作时需确保所有人理解转换规则。
  • 需保证目标方法的第一个参数是cls,否则批量转换后会引发参数不匹配的错误。

内容的提问来源于stack exchange,提问作者onimushawarlord

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 16:10:33