pydantic:当类字段由父类键入时,不正确
以下代码尝试序列化c
的实例,然后再次对c
进行后序列化。因为data
的类型信息在dict()
中丢失了,因此data
实例被解释为a
的实例/代码>而不是
b
(我的期望)。
我想要c_again
和c
相互匹配。我该怎么做?
from typing import Tuple, List
from pydantic import BaseModel
class A(BaseModel):
a: int
class B(A):
b: float
class C(BaseModel):
data: A
b = B(a=1, b=0.2)
c = C(data=b)
c_again = C(**c.dict())
print(c, ", ", c_again)
assert c == c_again
输出
data=B(a=1, b=0.2) , data=A(a=1)
Traceback (most recent call last):
File "/home/h-ishida/tmp/tmp.py", line 18, in <module>
assert c == c_again
AssertionError
The following code try to serialize the instance of C
to dict and then deserialize back to C
again. Because type information of data
is lost in serialization process in dict()
, the data
instance is interpreted as an instance of A
instead of B
(my expectation).
I want c_again
and c
match each other. How can I do this?
from typing import Tuple, List
from pydantic import BaseModel
class A(BaseModel):
a: int
class B(A):
b: float
class C(BaseModel):
data: A
b = B(a=1, b=0.2)
c = C(data=b)
c_again = C(**c.dict())
print(c, ", ", c_again)
assert c == c_again
output
data=B(a=1, b=0.2) , data=A(a=1)
Traceback (most recent call last):
File "/home/h-ishida/tmp/tmp.py", line 18, in <module>
assert c == c_again
AssertionError
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在 @bc291的评论上进行构建:
您需要的起点是键入
data
作为几种可能类型的union
,在您的示例中数据:联合[A,B]
。但这还不够:如果您只这样做,Pydantic将尝试将您的数据与它可以完成的第一个类型匹配,因此它仍然可以实例化c_again.data
asa( a = 1)
,忽略b
键/属性。您可以首先在联合中使用类型b
来解决此问题,例如union [b,a]
,它既行之有效,又不优雅,也不会强大,尤其是在您的实际用例涉及您所说的许多子类。因此,您还需要将
config
添加到a
,如果存在b
,它将使Pydantic拒绝实例化,因此它将跳过它并实例化Union
的类,该类改为匹配所有密钥/属性(在这种情况下,b
)。请注意,旨意继承这种行为的sublasses。输出:
Building up on @bc291 's comment:
What you need as a starting point is to type-hint
data
as aUnion
of several possible types, in your exampledata: Union[A, B]
. But that won't be enough: if you do only that, pydantic will try to match your data to the first type it can complete, so it would still instantiatec_again.data
asA(a=1)
, ignoring theb
key/attribute. You could work around this by type-hintingB
first in the union, likeUnion[B, A]
, that works but it would be neither elegant nor robust, especially if your actual use case involves many subclasses like you said.So, you also need to add a
Config
toA
that will make pydantic refuse to instantiate it ifb
is present, so it will skip it and instantiate a class of theUnion
that matches all the keys/attributes instead (in this case,B
). Note that sublasses of A will inherit this behaviour.Output: