如何获取被装饰类的原类名及对应类对象
解决装饰器导致类对象被替换为函数的问题
方案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
相关产品推荐
相关产品推荐

