如何在Pydantic模型中排除字段以避免__eq__递归错误?
解决Pydantic模型循环引用导致的递归比较栈溢出问题
核心原因
list.remove()方法会调用对象的__eq__进行相等性判断,而Pydantic默认的__eq__会递归比较所有字段。当模型存在循环引用(如previous_model互相指向)时,递归比较会触发RecursionError。
解决方案:重写__eq__方法排除指定字段
直接在SomeModel中重写__eq__方法,只比较需要的字段(name和content),忽略previous_model:
Pydantic v1 代码示例
import typing import pydantic class SomeModel(pydantic.BaseModel): name: str content: str previous_model: typing.Optional["SomeModel"] = None def __eq__(self, other): if not isinstance(other, SomeModel): return False # 只比较name和content字段 return self.name == other.name and self.content == other.content # 测试代码 models = [ SomeModel(name="bob", content="2"), SomeModel(name="bob", content="2"), ] models[0].previous_model = models[1] models[1].previous_model = models[0] models.remove(models[0]) # 现在不会触发递归错误
Pydantic v2 代码示例
如果使用Pydantic v2,写法类似,只是导入路径略有不同:
import typing from pydantic import BaseModel class SomeModel(BaseModel): name: str content: str previous_model: typing.Optional["SomeModel"] = None def __eq__(self, other: object) -> bool: if not isinstance(other, SomeModel): return False return self.name == other.name and self.content == other.content
补充说明
- 重写
__eq__时,先判断other的类型,避免和非SomeModel对象比较出错。 - 如果需要排除多个字段,可以扩展比较逻辑,比如提取需要比较的字段列表统一处理:
def __eq__(self, other): if not isinstance(other, SomeModel): return False # 定义需要比较的字段列表 compare_fields = {"name", "content"} return all(getattr(self, field) == getattr(other, field) for field in compare_fields)
内容的提问来源于stack exchange,提问作者mousetail
相关产品推荐
相关产品推荐

