如何在Python继承链中实现嵌套__init__合并各层类字典,优先不重写init方法
问题原因
你之前的实现错误原因是:继承链上所有__init__方法调用时,self始终是最下层的子类实例,通过self.specificator访问属性时,Python属性查找规则会直接拿到最下层子类定义的specificator,所以每层合并的都是同一个子类的字典,最终只能得到{'third':3}。
可行方案(无需子类重写__init__)
方案1:基类初始化时遍历MRO合并
仅需修改基类First的__init__方法,遍历当前类的方法解析顺序(MRO)收集所有父类的specificator合并即可,子类不需要做任何改动:
class First: specificator = {'first': 1} def __init__(self, *args, **kwargs): # 调用父类的__init__,兼容多继承场景 super().__init__(*args, **kwargs) self.inherited_specificator = {} # 遍历MRO链,排除末端的object类,倒序保证父类属性先写入、子类属性可覆盖 for cls in reversed(type(self).__mro__[:-1]): if hasattr(cls, 'specificator'): self.inherited_specificator.update(cls.specificator) class Second(First): specificator = {'second': 2} class Third(Second): specificator = {'third': 3}
测试效果:
print(Third().inherited_specificator) # 输出:{'first': 1, 'second': 2, 'third': 3}
方案2:元类预计算类级别的合并属性
如果类继承关系固定,且需要高频访问合并后的specificator,可以用元类在类定义阶段就预计算好合并结果作为类属性,不需要每次实例化都重新计算:
class SpecMeta(type): def __new__(cls, name, bases, attrs): new_cls = super().__new__(cls, name, bases, attrs) combined = {} # 类定义阶段直接遍历MRO合并 for base in reversed(new_cls.__mro__[:-1]): if hasattr(base, 'specificator'): combined.update(base.specificator) new_cls.inherited_specificator = combined return new_cls class First(metaclass=SpecMeta): specificator = {'first': 1} class Second(First): specificator = {'second': 2} class Third(Second): specificator = {'third': 3}
该方案无需实例化即可访问合并结果:
print(Third.inherited_specificator) # 输出:{'first': 1, 'second': 2, 'third': 3}
内容的提问来源于stack exchange,提问作者vodaniil
相关产品推荐
相关产品推荐

