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

Python实现经典装饰器模式 如何让被装饰实例通过原类isinstance校验

解决方案

你可以根据自己的场景选择以下两种常用实现方案:

方案1:重写__class__属性(最简单,无需修改原类)

Python的isinstance检查会优先读取实例的__class__属性做判断,只需要在抽象装饰器类中添加一个__class__属性的getter,直接返回被装饰实例的类型即可:

class AbstractDecorator:
    base_class: type = None

    def __init__(self, instance):
        self.instance = instance

    def __getattr__(self, item):
        # 若当前对象不存在对应属性或方法,则从被装饰的实例中查找
        return getattr(self.instance, item)
    
    @property
    def __class__(self):
        # isinstance检查时直接返回被装饰实例的类型
        return self.instance.__class__

测试效果:

original = Original()
decorated = ConcreteDecorator(original)
print(isinstance(decorated, Original)) # 输出 True

优劣说明:

  • 优点:代码最少,不需要修改原类定义,多层装饰也能正常生效
  • 缺点:会覆盖装饰器本身的类型判断,isinstance(decorated, ConcreteDecorator)会返回False,如果不需要判断装饰器自身类型的场景最适合用这个方案。

方案2:虚拟子类注册(同时保留装饰器自身类型判断)

如果你需要同时支持isinstance(decorated, 原类)和isinstance(decorated, 装饰器类)两种判断,可以用Python的ABC虚拟子类机制:

  1. 给原类指定ABCMeta元类
  2. 把具体装饰器类注册为原类的虚拟子类
from abc import ABCMeta

# 原类指定ABCMeta元类
class Original(metaclass=ABCMeta):
    def __init__(self):
        self.some_val = 1

class ConcreteDecorator(AbstractDecorator):
    base_class = Original

# 注册为原类的虚拟子类
Original.register(ConcreteDecorator)

测试效果:

original = Original()
decorated = ConcreteDecorator(original)
print(isinstance(decorated, Original)) # 输出 True
print(isinstance(decorated, ConcreteDecorator)) # 输出 True

优劣说明:

  • 优点:两种类型判断都能正常工作,完全符合Python的类型规范
  • 缺点:需要修改原类的元类定义,如果原类是第三方库提供的无法修改的话不适用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 14:15:04