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

能否无需显式指定父类名,将父类方法用作子类方法装饰器?

解决方案:隐式引用父类的delayed_init装饰器

你可以通过几种方式避免硬编码父类名称Manager,实现对父类装饰器的隐式引用,以下是几种可行方案:

方案1:使用类级别的super()引用

在子类定义阶段,通过super(子类名, 子类名)直接获取父类的装饰器,无需硬编码父类名称:

import numpy as np

class Manager:
    def __init__(self, value, delay_init=True):
        self.value = value
        self.is_init = False
        self.data = None

        if not delay_init:
            self._initialize()

    @staticmethod 
    def delayed_init(fn):
        def wrapped_delayed_init(obj, *args, **kwargs):
            if not obj.is_init:
                obj.data = np.random.randn(obj.value, obj.value)
                obj.is_init = True

            return fn(obj, *args, **kwargs)

        return wrapped_delayed_init

    @delayed_init.__get__(object)
    def _initialize(self):
        pass


class DataManager(Manager):
    def __init__(self, value):
        super().__init__(value)

    # 使用类级别的super获取父类的delayed_init装饰器
    @super(DataManager, DataManager).delayed_init
    def calculate_mean(self):
        return np.mean(self.data)

data_manager = DataManager(100)
assert data_manager.data is None
mean = data_manager.calculate_mean()

super(DataManager, DataManager)会返回父类Manager的类上下文,从而直接访问其静态方法delayed_init。

方案2:在子类中定义代理装饰器

在子类内部定义一个代理装饰器,通过super()隐式调用父类的装饰器,后续子类方法只需使用这个代理装饰器即可:

import numpy as np

class Manager:
    # 保持原有代码不变
    def __init__(self, value, delay_init=True):
        self.value = value
        self.is_init = False
        self.data = None

        if not delay_init:
            self._initialize()

    @staticmethod 
    def delayed_init(fn):
        def wrapped_delayed_init(obj, *args, **kwargs):
            if not obj.is_init:
                obj.data = np.random.randn(obj.value, obj.value)
                obj.is_init = True

            return fn(obj, *args, **kwargs)

        return wrapped_delayed_init

    @delayed_init.__get__(object)
    def _initialize(self):
        pass


class DataManager(Manager):
    def __init__(self, value):
        super().__init__(value)

    # 定义代理装饰器,隐式调用父类的delayed_init
    @classmethod
    def delayed_init(cls, fn):
        return super().delayed_init(fn)

    # 使用子类的代理装饰器
    @delayed_init
    def calculate_mean(self):
        return np.mean(self.data)

data_manager = DataManager(100)
assert data_manager.data is None
mean = data_manager.calculate_mean()

该方案让子类方法的装饰器写法更简洁,且完全与父类名称解耦。

方案3:使用元类自动装饰标记方法

如果有多个需要延迟初始化的方法,可以通过元类自动识别标记的方法,自动应用父类的delayed_init装饰器:

import numpy as np

# 定义标记装饰器,用来标记需要延迟初始化的方法
def needs_delayed_init(fn):
    fn._needs_delayed_init = True
    return fn

# 定义元类,自动装饰标记的方法
class ManagerMeta(type):
    def __new__(cls, name, bases, attrs):
        # 遍历类属性,找到标记的方法并应用父类的delayed_init
        for attr_name, attr in attrs.items():
            if callable(attr) and hasattr(attr, '_needs_delayed_init'):
                attrs[attr_name] = bases[0].delayed_init(attr)
        return super().__new__(cls, name, bases, attrs)

class Manager(metaclass=ManagerMeta):
    def __init__(self, value, delay_init=True):
        self.value = value
        self.is_init = False
        self.data = None

        if not delay_init:
            self._initialize()

    @staticmethod 
    def delayed_init(fn):
        def wrapped_delayed_init(obj, *args, **kwargs):
            if not obj.is_init:
                obj.data = np.random.randn(obj.value, obj.value)
                obj.is_init = True

            return fn(obj, *args, **kwargs)

        return wrapped_delayed_init

    @delayed_init.__get__(object)
    def _initialize(self):
        pass


class DataManager(Manager):
    def __init__(self, value):
        super().__init__(value)

    # 只需添加标记装饰器,元类会自动应用父类的delayed_init
    @needs_delayed_init
    def calculate_mean(self):
        return np.mean(self.data)

data_manager = DataManager(100)
assert data_manager.data is None
mean = data_manager.calculate_mean()

该方案无需手动引用任何父类装饰器,只需给目标方法添加标记即可完成自动装饰。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 17:54:32