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

Python继承dict内置类时触发RecursionError的问题求助

解决继承dict时创建实例触发RecursionError的问题

嘿,这问题我熟!继承Python内置dict时踩这个递归坑太常见了,核心原因几乎都是你重写的方法不小心触发了无限递归调用,咱们来拆解最典型的场景和解决办法:

最常见的错误场景:__setitem__方法的递归调用

很多人在写带校验的dict子类时,会重写__setitem__来做键值校验,但一不小心就写成了这样:

class ValidatedDict(dict):
    def __setitem__(self, key, value):
        # 自定义校验逻辑
        if not isinstance(key, str):
            raise TypeError("键必须是字符串类型")
        # 错误:这里直接用self[key] = value,会再次调用自己的__setitem__
        self[key] = value

当你尝试创建实例(比如vd = ValidatedDict(name="Alice"))时,初始化过程中会调用__setitem__,而里面的self[key] = value又会再次触发你重写的__setitem__,无限循环下去,直到Python的调用栈耗尽,就抛出了RecursionError。

正确的写法:调用父类的方法

解决办法很简单——不要调用自己的__setitem__,而是通过super()调用父类dict的原生方法:

class ValidatedDict(dict):
    def __setitem__(self, key, value):
        # 先执行你的校验逻辑
        if not isinstance(key, str):
            raise TypeError("键必须是字符串类型")
        if not isinstance(value, (int, str)):
            raise TypeError("值只能是整数或字符串")
        # 调用父类的__setitem__完成实际赋值
        super().__setitem__(key, value)

    def __init__(self, *args, **kwargs):
        # 先校验传入的键值对
        validated_args = []
        for item in args:
            if isinstance(item, dict):
                validated_item = {k: v for k, v in item.items() if self._validate(k, v)}
                validated_args.append(validated_item)
        validated_kwargs = {k: v for k, v in kwargs.items() if self._validate(k, v)}
        # 调用父类初始化
        super().__init__(*validated_args, **validated_kwargs)

    # 把校验逻辑抽成私有方法,复用性更好
    def _validate(self, key, value):
        return isinstance(key, str) and isinstance(value, (int, str))

另一个容易踩的坑:__init__里的错误赋值

如果你在__init__里直接用self[key] = value来初始化实例,而没有先调用父类的__init__,也会触发同样的递归问题。比如:

class ValidatedDict(dict):
    def __init__(self, **kwargs):
        # 错误:这里的self[key] = value会调用自己的__setitem__,如果__setitem__又没处理好就递归
        for key, value in kwargs.items():
            self[key] = value

这种情况要么像上面那样先校验再通过super().__init__传递参数,要么在循环里直接调用super().__setitem__(key, value)来避免触发自己的方法。

总结一下核心要点

  • 继承内置dict时,重写__setitem__、update、__init__这些方法时,必须明确通过super()调用父类的对应方法,避免触发自身方法的无限递归。
  • 所有涉及键值赋值的操作,只要不是要触发你的校验逻辑,都直接用父类的方法来完成。

内容的提问来源于stack exchange,提问作者Ger

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:57:32