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

继承dict传入自定义对象触发TypeError的问题排查

继承dict时传入自定义对象列表触发TypeError的原因及解决方法

问题根源

你只重写了__new__方法处理参数,但忽略了dict的初始化流程:当__new__创建完实例后,__init__会自动执行,并且它会直接使用原始构造参数(未经过__new__处理的列表)去尝试更新字典。而你的列表里是TextureItem对象,不是dict要求的键值对序列(比如元组或其他可迭代的键值结构),所以触发了cannot convert dictionary update sequence element #0 to a sequence错误。

关键逻辑验证

dict的初始化顺序是:

  1. 调用__new__创建实例;
  2. 如果__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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 07:17:41