如何通过Python装饰器实现子类访问父类实例的间接继承?
实现
subcollection装饰器:让嵌套子类访问父类实例 完全可以通过装饰器实现这个需求,无需工厂函数。核心思路是用装饰器标记子类并重写其初始化逻辑,同时让父类在访问子类时自动传递自身实例给子类。
装饰器与类的实现代码
def subcollection(cls): # 标记该类为子集合类 cls._is_subcollection = True # 保存原始初始化方法 original_init = cls.__init__ def wrapped_init(self, parent_instance, *args, **kwargs): self.parent = parent_instance original_init(self, *args, **kwargs) # 替换子类的初始化方法,使其接收父实例 cls.__init__ = wrapped_init return cls class ParentClass: def __init__(self, name): self.name = name def __getattr__(self, attr_name): # 从父类的类属性中查找目标子类 target_cls = getattr(self.__class__, attr_name, None) # 判断是否是被标记的子集合类 if target_cls and hasattr(target_cls, '_is_subcollection') and target_cls._is_subcollection: # 返回一个绑定了父实例的创建函数,支持子类初始化传参 def create_child(*args, **kwargs): return target_cls(self, *args, **kwargs) return create_child raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{attr_name}'") # 用装饰器标记子类 @subcollection class ChildClass: def greet(self): print(f"Hello from Child, parent name is {self.parent.name}")
测试验证
# 创建父类实例 parent = ParentClass("Alice") # 创建子类实例(自动传入父实例) child = parent.ChildClass() # 调用子类方法,访问父类属性 child.greet() # 输出:Hello from Child, parent name is Alice
原理说明
- 装饰器
subcollection:给子类添加标记_is_subcollection,并重写__init__方法,让子类实例初始化时接收并保存父类实例到self.parent属性。 - 父类
__getattr__方法:当父类实例访问嵌套的子类时,自动检测该子类是否被装饰器标记。如果是,返回一个绑定了父实例的创建函数,调用该函数时会自动把父实例传递给子类的初始化方法。 - 灵活性:如果子类需要额外初始化参数,直接在创建时传入即可,比如
parent.ChildClass("extra_param"),参数会被传递给子类原始的__init__方法。
内容的提问来源于stack exchange,提问作者Mahdi Jadaliha
相关产品推荐
相关产品推荐

