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
相关产品推荐
相关产品推荐

