是否可以指定包含在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})
唯一的区别是User
的stats
字段是一个类(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
:
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
字典中提供错误类型的值。