在pydantic模型中单独指定嵌套字典字段



是否可以指定包含在pydantic模型中的字典中的单个字段?我没有找到任何东西,但也许我用错了关键字。我在想这样的事情:

from pydantic import BaseModel
class User(BaseModel):
id: int
name: str = 'Jane Doe'
stats = {
age: int,
height: float,
}

编辑:经过一些反馈,我觉得我需要澄清一点这一点的一些条件,并给出一个更完整的例子。我想要做的更类似于:

from pydantic import BaseModel, NonNegativeInt, NonNegativeFloat
from pydantic.generics import GenericModel
DataT = TypeVar('DataT')
class Trait(GenericModel, Generic[DataT]):
descript: str
value: DataT
class CharacterBarbarian(BaseModel):
id: int
name: str = 'Barbarok'
traits = {
strength: Trait[NonNegativeInt] = Trait[NonNegativeInt](descript='the force', value=18),
height: Trait[NonNegativeFloat] = Trait[NonNegativeFloat](descript='tallness', value=1.8),
weight: Trait[NonNegativeFloat] = Trait[NonNegativeFloat](descript='width', value=92.1),
}
class CharacterWizard(BaseModel):
id: int
name: str = 'Supremus'
traits = {
intelligence: Trait[NonNegativeInt] = Trait[NonNegativeInt](descript='smarts', value=16),
spells: Trait[NonNegativeInt] = Trait[NonNegativeInt](descript='number of them', value=4),
}

SavedWizard_dict = { # Read from file for example
'id': 1234,
'name': "Gandalf",
'traits': {
'intelligence': {'descript': 'smarts', 'value': 20}
'spells': {'descript': 'number of them', 'value': 100),
},
}
SavedWizard = CharacterWizard(**SavedWizard_dict)

所以基本上我试图利用pydantic的内在能力来序列化/反序列化dict/json来保存和初始化我的类。同时,这些pydantic类由一个泛型pydantic类的特定版本的列表/字典组成,但这些选择因类而异。

您可以使用嵌套类做类似的事情:

from pydantic import BaseModel
class UserStats(BaseModel):
age: int
height: float
class User(BaseModel):
id: int
name = 'Jane Doe'
stats: UserStats

那么当你构建任何User实例时,你可以将stats字段作为字典传递,它将自动转换:

user = User(id=1234, stats={"age": 30, "height": 180.0})

唯一的区别是Userstats字段是一个类(UserStats的实例),所以如果你想访问它的字段,你需要使用属性访问而不是使用字典访问:

print(user.age)  # ok!
print(user["age"])  # not ok...

如果你需要ste stats属性是一个字典,那么你可以使用typing_extensions(python3.7)或typing(python3.8+)模块中的TypedDict:

from typing import TypedDict
from pydantic import BaseModel
class UserStats(TypedDict):
age: int
height: float
class User(BaseModel):
id: int
name = 'Jane Doe'
stats: UserStats
user = User(id=1234, stats={"age": 30, "height": 180.0})
print(user.stats["age"])  # will work!

编辑:

正如在这个回答的评论中提到的,作者不想全局定义UserStats类以避免污染。

这可以通过直接在User类中定义类来解决:

class User(BaseModel):
id: int
name = "Jane Doe"
class Stats(TypedDict):
age: int
height: float
stats: Stats

这允许像User这样的多个类各自定义它们的stats,而不需要在全局命名空间中重复Stats类。

对于类型检查器和语言服务器来说,使用TypedDict:

的功能API是一个更符合但不太友好的方法。
class User(BaseModel):
id: int
name = "Jane Doe"
stats: TypedDict("Stats", age=int, height=float)

为了完整起见,您还可以使用TypedDict提供的功能性API来编写您的模型,如下所示:

from typing import TypedDict
from pydantic import BaseModel

class User(BaseModel):
id: int
name = 'Jane Doe'
stats: TypedDict("Stats", {"age": int, "height": float})

我想不出比这更简洁的方法了。我一开始不确定这是如何与类型检查器一起发挥作用的,但至少PyCharm与Pydantic插件似乎没有问题正确推断类型并发出警告,如果你试图在stats字典中提供错误类型的值。

相关内容

  • 没有找到相关文章

最新更新