eud*_*xos 8 properties pydantic
我有一个派生类pydantic.BaseModel,并希望创建一个“假”属性,即计算属性。property 关键字似乎不能以通常的方式与 Pydantic 配合使用。下面是 MWE,其中类存储值并定义具有half明显含义的调用的读/写属性。使用 Pydantic 读取属性可以正常工作,但赋值失败。
我知道 Pydantic 正在修改属性访问的低级细节;也许有一种方法可以在 Pydantic 中以不同的方式定义计算域?
import pydantic
class Object(object):
def __init__(self,*,value): self.value=value
half=property(lambda self: .5*self.value,lambda self,h: setattr(self,'value',h*2))
class Pydantic(pydantic.BaseModel):
class Config:
extra='allow'
value: float
half=property(lambda self: .5*self.value,lambda self,h: setattr(self,'value',h*2))
o,p=Object(value=1.),Pydantic(value=1.)
print(o.half,p.half)
o.half=p.half=2
print(o.value,p.value)
Run Code Online (Sandbox Code Playgroud)
half输出(值=1。在 Pydantic 情况下未通过分配进行修改):
0.5 0.5
4 1.0
Run Code Online (Sandbox Code Playgroud)
ben*_*vdh 10
我今天碰巧正在研究同样的问题。正如此处所讨论的,官方尚不支持它。
但是,我确实发现以下示例效果很好:
class Person(BaseModel):
first_name: str
last_name: str
full_name: str = None
@validator("full_name", always=True)
def composite_name(cls, v, values, **kwargs):
return f"{values['first_name']} {values['last_name']}"
Run Code Online (Sandbox Code Playgroud)
请确保您的派生字段位于您想要从中派生的字段之后values,否则字典将不会包含所需的值(例如,full_name 位于需要从值中获取的first_name 和last_name 之后)。
更新:正如 Hyagoro 在下面提到的,Pydantic 2 现在有一个官方支持的计算字段装饰器。不幸的是,该功能不会向后移植到 Pydantic v1(来源)。所以在 Pydantic v2 中,上面的例子变成了:
from pydantic import BaseModel, computed_field
class Person(BaseModel):
first_name: str
last_name: str
full_name: str = None
@computed_field
@property
def composite_name(self):
return f"{self.first_name} {self.last_name}"
Run Code Online (Sandbox Code Playgroud)
小智 5
下面的示例展示了如何使用属性来pydantic.root_validator计算可选字段的值,而不是使用属性:
https://daniellenz.blog/2021/02/20/compulated-fields-in-pydantic/
我已将其改编为类似的应用程序:
class Section (BaseModel):
title: constr(strip_whitespace=True)
chunks: conlist(min_items=1, item_type=Chunk)
size: typing.Optional[ PositiveInt ] = None
role: typing.Optional[ typing.List[ str ]] = []
license: constr(strip_whitespace=True)
@root_validator
def compute_size (cls, values) -> typing.Dict:
if values["size"] is None:
values["size"] = sum([
chunk.get_size()
for chunk in values["chunks"]
])
return values
Run Code Online (Sandbox Code Playgroud)
在这种情况下,可区分联合 的每个元素chunks都有一个get_size()计算其大小的方法。如果size在序列化中未显式指定该字段(例如,从 JSON 文件输入),则会计算该字段。