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

如何获取被装饰类的原类名及对应类对象

解决装饰器导致类对象被替换为函数的问题

方案1:保留工厂函数逻辑,补充类元数据

若你的装饰器需返回工厂函数(如在实例创建前后执行额外逻辑),可通过functools.wraps复制原类的元数据,并显式保存原类引用,这样既能保留装饰逻辑,又能获取类的相关信息:

import typing
import functools

def mydeco(cls: type) -> typing.Callable:
    @functools.wraps(cls)
    def inner(*args: typing.Any, **kwargs: typing.Any) -> object:
        # 可在此添加实例创建前后的自定义逻辑(如日志、参数校验)
        return cls(*args, **kwargs)
    inner.__wrapped__ = cls  # 保存原类引用,方便后续获取
    return inner

@mydeco
class Wheels:
    def __init__(self, count: int) -> None:
        self.count = count

if __name__ == "__main__":
    print(Wheels.__name__)                # 输出: Wheels
    print(Wheels.__wrapped__)             # 输出: <class '__main__.Wheels'>
    print(Wheels.__wrapped__.__name__)    # 输出: Wheels

通过Wheels.__wrapped__可直接获取原类对象,Wheels.__name__则能拿到类名。

方案2:让装饰器返回类类型(符合类的常规使用习惯)

若无需返回工厂函数,可直接修改原类并返回,这样Wheels始终保持类类型,所有类相关属性均可正常访问:

import typing

def mydeco(cls: type) -> type:
    original_init = cls.__init__
    
    def new_init(self, *args: typing.Any, **kwargs: typing.Any) -> None:
        # 添加自定义逻辑,例如实例创建前的参数校验
        if args[0] <= 0:
            raise ValueError("车轮数量必须为正数")
        original_init(self, *args, **kwargs)
    
    cls.__init__ = new_init
    return cls

@mydeco
class Wheels:
    def __init__(self, count: int) -> None:
        self.count = count

if __name__ == "__main__":
    print(Wheels)                         # 输出: <class '__main__.Wheels'>
    print(Wheels.__name__)                # 输出: Wheels
    print(type(Wheels))                   # 输出: <class 'type'>

这种方式下,Wheels完全保留类的特性,同时能实现装饰器的自定义逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 05:27:42