提问人:mousetail 提问时间:8/14/2022 更新时间:8/14/2022 访问量:1664
Pydantic 从__eq__中排除字段以避免递归错误
Pydantic exclude field from __eq__ to avoid recursion error
问:
我有一个这样的pydantic模型:
class SomeModel(pydantic.BaseModel):
name: str
content: str
previous_model: typing.Optional["SomeModel"] = None
我的代码看起来像这样,这大大简化了,在我的实际代码中,有很多循环依赖关系偶尔偶然发生,而不是有目的地创建:
models = [
SomeModel("bob", "2"),
SomeModel("bob", "2"),
]
models[0].previous_model = models[1]
models[1].previous_model = models[0]
models.remove(models[0])
这会引发以下错误:
File "c:\Users\username\project-name\src\main.py", line 108, in run_all
models.remove(models[0])
File "pydantic\main.py", line 902, in pydantic.main.BaseModel.__eq__
File "pydantic\main.py", line 445, in pydantic.main.BaseModel.dict
File "pydantic\main.py", line 861, in _iter
File "pydantic\main.py", line 736, in pydantic.main.BaseModel._get_value
File "pydantic\main.py", line 445, in pydantic.main.BaseModel.dict
File "pydantic\main.py", line 861, in _iter
File "pydantic\main.py", line 736, in pydantic.main.BaseModel._get_value
File "pydantic\main.py", line 445, in pydantic.main.BaseModel.dict
File "pydantic\main.py", line 861, in _iter
File "pydantic\main.py", line 736, in pydantic.main.BaseModel._get_value
File "pydantic\main.py", line 445, in pydantic.main.BaseModel.dict
File "pydantic\main.py", line 861, in _iter
File "pydantic\main.py", line 736, in pydantic.main.BaseModel._get_value
File "pydantic\main.py", line 445, in pydantic.main.BaseModel.dict
File "pydantic\main.py", line 861, in _iter
... Snip several hunderd more lines
File "pydantic\main.py", line 734, in pydantic.main.BaseModel._get_value
File "pydantic\main.py", line 304, in pydantic.main.ModelMetaclass.__instancecheck__
RecursionError: maximum recursion depth exceeded
我真的根本不需要将该字段包含在相等中。有没有办法排除它,这样我的堆栈就不会溢出?在这种情况下,此字段与目的相等无关。previous_model
答:
3赞
Tom Wojcik
8/14/2022
#1
当 pydantic 生成时,它会遍历它的参数。这是有道理的,这是关键卖点之一。但它在你的场景中效果不佳,你必须省略它才能使其工作。您可以跳入或返回更简单的内容。给你一个非常简化的例子,它正在工作__repr__
previous_node
__repr__
previous_node
__repr_args__
__repr__
import typing
import pydantic
class SomeModel(pydantic.BaseModel):
name: str
content: str
previous_model: typing.Optional["SomeModel"] = None
def __repr__(self):
return self.name
SomeModel.update_forward_refs()
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])
print(models)
不太简单的版本,更接近 pydantic 的行为方式,但也适用于您的情况
import typing
import pydantic
class SomeModel(pydantic.BaseModel):
name: str
content: str
previous_model: typing.Optional["SomeModel"] = None
def __repr_args__(self, *args, **kwargs):
args = self.dict(exclude={'previous_model',})
return list(args.items())
SomeModel.update_forward_refs()
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])
上一个:相等是否意味着相等的哈希值?
评论