继承dict传入自定义对象触发TypeError的问题排查
继承dict时传入自定义对象列表触发TypeError的原因及解决方法
问题根源
你只重写了__new__方法处理参数,但忽略了dict的初始化流程:当__new__创建完实例后,__init__会自动执行,并且它会直接使用原始构造参数(未经过__new__处理的列表)去尝试更新字典。而你的列表里是TextureItem对象,不是dict要求的键值对序列(比如元组或其他可迭代的键值结构),所以触发了cannot convert dictionary update sequence element #0 to a sequence错误。
关键逻辑验证
dict的初始化顺序是:
- 调用
__new__创建实例; - 如果
__new__返回当前类的实例,立即调用__init__,并把最初传入的参数原封不动传给__init__。
你在__new__里处理了参数,但__init__拿到的还是未处理的原始列表,自然会报错。
解决方案
方案1:同时重写__init__跳过默认逻辑
如果__new__已经完成了参数处理和实例初始化,可以让__init__什么都不做,避免父类__init__用原始参数更新实例:
class GlobalPalette(dict): def __new__(cls, *args, **kwargs): # 处理参数:将TextureItem列表转为键值对字典 processed_args = [] for arg in args: if isinstance(arg, list) and all(isinstance(item, TextureItem) for item in arg): processed_args.append({item.key: item.value for item in arg}) else: processed_args.append(arg) # 调用父类__new__创建实例 return super().__new__(cls, *processed_args, **kwargs) def __init__(self, *args, **kwargs): # 跳过父类__init__,避免用原始参数更新 pass
方案2:只重写__init__统一处理参数
相比重写__new__,直接在__init__里处理参数更符合常规类的初始化逻辑,也更直观:
class GlobalPalette(dict): def __init__(self, *args, **kwargs): # 预处理所有参数,将TextureItem列表转为键值对结构 processed_args = [] for arg in args: if isinstance(arg, list) and all(isinstance(item, TextureItem) for item in arg): processed_args.append({item.key: item.value for item in arg}) else: processed_args.append(arg) # 调用父类__init__完成字典初始化 super().__init__(*processed_args, **kwargs)
额外建议
如果不是必须直接继承dict,推荐使用collections.UserDict作为父类。它是纯Python实现的字典包装类,继承时不会有内置类型的初始化陷阱,自定义逻辑会更顺畅。
内容的提问来源于stack exchange,提问作者hmngwn
相关产品推荐
相关产品推荐

