Python继承内置类型搭配super使用时list与其他类型表现差异问题
问题成因
你遇到的差异本质是Python内置类型的初始化逻辑分为两类,且你采用的多继承方案受方法解析顺序(MRO)影响:
- 不可变类型(int、str、tuple等):实例值的构造完全在
__new__方法中完成,__init__方法继承自object,不接收额外参数,也不会修改实例值。你传入的初始化参数在__new__阶段就已经写入实例,因此哪怕你在Value.__init__中调用无参的super().__init__()也不会报错,实例值也正常。 - 可变类型(list、dict、set等):
__new__方法只会生成空的容器实例,元素填充逻辑在__init__方法中实现,必须传入初始化参数才能生成非空实例。你的Value.__init__调用无参super().__init__()时,父类的__init__没有拿到你传入的列表,因此最终生成空实例。
直接统一给super().__init__(value)传参会报错,是因为不可变类型的__init__不接收额外参数,传参就会触发类型错误。
推荐实现方案
提供两种可选方案,可根据你的使用场景选择:
方案1:代理模式(更稳妥,无兼容问题)
不需要继承内置类型,直接用属性转发模拟内置类型的所有行为,完全规避初始化逻辑差异问题:
class Value: def __init__(self, value, **extra_attrs): self._inner = value # 批量添加额外属性 for k, v in extra_attrs.items(): setattr(self, k, v) # 转发普通属性访问 def __getattr__(self, item): return getattr(self._inner, item) # 转发容器操作的魔术方法,根据需要补充即可 def __getitem__(self, item): return self._inner[item] def __setitem__(self, key, value): self._inner[key] = value def __delitem__(self, key): del self._inner[key] def __len__(self): return len(self._inner) def __repr__(self): return repr(self._inner) def __add__(self, other): return self._inner + other
使用时不需要动态构造多继承类,直接传入对应值即可:
# 模拟int类型 var1 = Value(1, extra_tag="test_int") print(var1 + 2) # 输出3,和普通int行为一致 print(var1.extra_tag) # 输出test_int,可正常访问额外属性 # 模拟list类型 var2 = Value(['some', 'list'], extra_tag="test_list") print(var2[0]) # 输出some,和普通list行为一致 var2.append('new') print(var2) # 输出['some', 'list', 'new']
方案2:继承方案(适配需要完全兼容内置类型特性的场景)
如果必须用多继承的实现方式,可直接判断实例所属的父类类型,覆盖所有常用可变容器类型即可,不需要判断参数类型:
class Value: def __init__(self, value, *args, **kwargs): # 仅可变容器类型需要传入参数调用父类__init__ mutable_types = (list, dict, set, bytearray) if isinstance(self, mutable_types): super().__init__(value, *args, **kwargs) else: super().__init__() # 你的额外初始化逻辑写在这里
你原来动态构造类的代码不需要修改,即可同时兼容可变、不可变内置类型。
内容的提问来源于stack exchange,提问作者Daniel Konopka
相关产品推荐
相关产品推荐

