标准库类型
description: 对 Python 标准库中常见类型的支持。
Pydantic 支持 Python 标准库中的许多常见类型。如果您需要更严格的处理,请参见严格类型,包括如果您需要约束允许的值(例如,要求一个正的 int)。
Note
Pydantic 仍然支持较旧的(3.8 之前的)类型构造,如 typing.List 和 typing.Dict,但最佳实践是使用较新的类型,如 list 和 dict。
布尔值¶
如果值不是以下之一,标准的 bool 字段将引发 ValidationError:
- 一个有效的布尔值(即
True或False), - 整数
0或1, - 一个
str,当其转换为小写时是以下之一'0', 'off', 'f', 'false', 'n', 'no', '1', 'on', 't', 'true', 'y', 'yes' - 一个
bytes,当解码为str时符合前一条规则
Note
如果您想要更严格的布尔逻辑(例如,一个只允许 True 和 False 的字段),您可以使用 StrictBool。
以下是一个演示其中一些行为的脚本:
from pydantic import BaseModel, ValidationError
class BooleanModel(BaseModel):
bool_value: bool
print(BooleanModel(bool_value=False))
#> bool_value=False
print(BooleanModel(bool_value='False'))
#> bool_value=False
print(BooleanModel(bool_value=1))
#> bool_value=True
try:
BooleanModel(bool_value=[])
except ValidationError as e:
print(str(e))
"""
1 validation error for BooleanModel
bool_value
Input should be a valid boolean [type=bool_type, input_value=[], input_type=list]
"""
日期时间类型¶
Pydantic 支持以下 datetime 类型:
datetime.datetime¶
datetime字段将接受以下类型的值:datetime;一个现有的datetime对象int或float;假定为 Unix 时间,即自 1970 年 1 月 1 日以来的秒数(如果 >=-2e10且 <=2e10)或毫秒数(如果 <-2e10或 >2e10)str;接受以下格式:YYYY-MM-DD[T]HH:MM[:SS[.ffffff]][Z or [±]HH[:]MM]YYYY-MM-DD在宽松模式下被接受,但在严格模式下不被接受int或float作为字符串(假定为 Unix 时间)
datetime.date实例在宽松模式下被接受,但在严格模式下不被接受
from datetime import datetime
from pydantic import BaseModel
class Event(BaseModel):
dt: datetime = None
event = Event(dt='2032-04-23T10:20:30.400+02:30')
print(event.model_dump())
"""
{'dt': datetime.datetime(2032, 4, 23, 10, 20, 30, 400000, tzinfo=TzInfo(9000))}
"""
datetime.date¶
date字段将接受以下类型的值:date;一个现有的date对象int或float;处理方式与上面描述的datetime相同str;接受以下格式:YYYY-MM-DDint或float作为字符串(假定为 Unix 时间)
from datetime import date
from pydantic import BaseModel
class Birthday(BaseModel):
d: date = None
my_birthday = Birthday(d=1679616000.0)
print(my_birthday.model_dump())
#> {'d': datetime.date(2023, 3, 24)}
datetime.time¶
-
time字段将接受以下类型的值:time;一个现有的time对象str;接受以下格式:HH:MM[:SS[.ffffff]][Z or [±]HH[:]MM]
from datetime import time
from pydantic import BaseModel
class Meeting(BaseModel):
t: time = None
m = Meeting(t=time(4, 8, 16))
print(m.model_dump())
#> {'t': datetime.time(4, 8, 16)}
datetime.timedelta¶
-
timedelta字段将接受以下类型的值:timedelta;一个现有的timedelta对象int或float;假定为秒str;接受以下格式:[-][[DD]D,]HH:MM:SS[.ffffff]- 例如:
'1d,01:02:03.000004'或'1D01:02:03.000004'或'01:02:03'
- 例如:
[±]P[DD]DT[HH]H[MM]M[SS]S(ISO 8601 格式的 timedelta)
from datetime import timedelta
from pydantic import BaseModel
class Model(BaseModel):
td: timedelta = None
m = Model(td='P3DT12H30M5S')
print(m.model())
#> {'td': datetime.timedelta(days=3, seconds=45005)}
数字类型¶
Pydantic 支持 Python 标准库中的以下数字类型:
int¶
- Pydantic 使用
int(v)将类型强制转换为int; 有关数据转换期间信息丢失的详细信息,请参见数据转换。
float¶
- Pydantic 使用
float(v)将值强制转换为浮点数。
enum.IntEnum¶
- 验证:Pydantic 检查该值是否为有效的
IntEnum实例。 - 对
enum.IntEnum子类的验证:检查该值是否为整数枚举的有效成员; 有关更多详细信息,请参见枚举和选择。
decimal.Decimal¶
- 验证:Pydantic 尝试将值转换为字符串,然后将字符串传递给
Decimal(v)。 - 序列化:Pydantic 将
Decimal类型序列化为字符串。 如果需要,您可以使用自定义序列化器来覆盖此行为。例如:
from decimal import Decimal
from typing import Annotated
from pydantic import Base, PlainSerializer
class Model(Base):
x: Decimal
y: Annotated[
Decimal,
PlainSerializer(
lambda x: float(x), return_type=float, when_used='json'
),
]
my_model = Model(x=Decimal('1.1'),=Decimal('2.1'))
print(my_model.model_dump()) # (1)!
#> {'x': Decimal('1.1'), 'y': Decimal('2.1')}
print(my_model.model_dump(mode='json')) # (2)!
#> {'x': '1.1', 'y': 2.1}
print(my_model.model_dump_json()) (3)!
#> {"x":"1.1","y":2.1}
- 使用
model_dump,x和y都保持Decimal类型的实例 - 使用
model_dump和mode='json',x被序列化为string,而y由于应用了自定义序列化器而被序列化为float。 - 使用
model_dump_json,x被序列化为string,而y由于应用了自定义序列化器而被序列化为float。
complex¶
- 验证:Pydantic 支持
complex类型或可以转换为complex类型的str值。 - 序列:Pydantic 将
complex类型序列化为字符串。
fractions.Fraction¶
- 验证:Pydantic 尝试使用
Fraction(v)将值转换为Fraction。 - 序列化:Pydantic 将 [
Fraction][fractionsFraction] 类型序列化为字符串。
Enum¶
Pydantic 使用 Python 的标准 enum 类来定义选择。
enum.Enum 检查该值是否为有效的 Enum 实例。
enum.Enum 的子类检查该值是否为枚举的有效成员。
from enum import Enum, IntEnum
from pydantic import BaseModel, ValidationError
class FruitEnum(str, Enum):
pear = 'pear'
banana = 'banana'
class ToolEnum(IntEnum):
spanner = 1
wrench = 2
class CookingModel(BaseModel):
fruit: FruitEnum = FruitEnum.pear
tool: ToolEnum = ToolEnum.spanner
print(CookingModel())
#> fruit=<FruitEnum.pear: 'pear'> tool=<ToolEnum.spanner: 1>
print(CookingModel(tool=2, fruit='banana'))
#> fruit=<FruitEnum.banana: 'banana'> tool=<ToolEnum.wrench: 2>
try:
CookingModel(fruit='other')
except ValidationError as e:
print(e)
"""
1 validation error for CookingModel
fruit
Input should be '' or 'banana' [type=enum, input_value='other', input_type=str]
"""
列表和元组¶
list¶
允许 list、tuple、set、frozenset、deque 或生成器,并强制转换为 list。
当提供泛型参数时,适当的验证将应用于列表的所有项目。
from typing import Optional
from pydantic import BaseModel
class Model(BaseModel):
simple_list: Optional[list] = None
list_of_ints: Optional[list[int]] = None
print(Model(simple_list=['1', '2', '3']).simple_list)
#> ['1', '2', '3']
print(Model(list_of_ints=['1', '2', '3']).list_of)
#> [1, 2, 3]
from pydantic import BaseModel
class Model(BaseModel):
simple_list: list | None = None
list_of_ints: list[int] | None = None
print(Model(simple_list=['1', '2', '3']).simple_list)
#> ['1', '2', '3']
print(Model(list_of_ints=['1', '2', '3']).list_of)
#> [1, 2, 3]
tuple¶
允许 list、tuple、[`][]、[frozenset][]、[deque][collections.deque] 或生成器,并强制转换为 [tuple`][``][]、[`frozenset`][]、[`deque`][collections.deque] 或生成器,并强制转换为 [`tuple`]。
当提供泛型参数时,适当的验证将应用于元组的相应项目。
typing.Tuple¶
处理方式与上面的 tuple 相同。
from typing import Optional
from pydantic import BaseModel
class Model(BaseModel):
simple_tuple: Optional[tuple] =
tuple_of_different_types: Optional[tuple[int, float, bool]] = None
print(Model(simple_tuple=[1, 2, 3, 4]).simple_tuple)
#> (1, 2, 3, 4)
print(Model(tuple_of_different_types=[3, 2, 1]).tuple_of_different_types)
#> (3, 2.0, True)
typing.NamedTuple¶
typing.NamedTuple 的子类类似于 tuple,但会创建给定 namedtuple 类的实例。
collections.namedtuple 的子类类似于 typing.NamedTuple 的子类,但由于未指定字段类型,所有字段都被视为具有类型 Any。
from typing import NamedTuple
from pydantic import BaseModel, ValidationError
class Point(Named):
x: int
y: int
class Model(BaseModel):
p: Point
try:
Model(p=('1.3', '2'))
except ValidationError as e:
print(e)
"""
1 validation error for Model
p.0
Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='1.3', input_type=str]
"""
from pydantic import BaseModel, ValidationError
class Point(Named):
x: int
y: int
class Model(BaseModel):
p: Point
try:
Model(p=('1.3', '2'))
except ValidationError as e:
print(e)
"""
1 validation error for Model
p.0
Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='1.3', input_type=str]
"""
双端队列¶
de¶
允许 list、tuple、set、frozenset、deque 或生成器,并强制转换为 deque。
当提供泛型参数时,适当的验证将应用于 deque 的相应项目。
typing.Deque¶
处理方式与 deque 相同。
from typing import Deque, Optional
from pydantic import BaseModel
class Model(BaseModel):
deque: Optional[Deque[int]] = None
print(Model(deque=[1, 2, 3]).deque)
#> deque([1, 2, 3])
from typing import Deque
from pydantic import BaseModel
class Model(BaseModel):
deque: Deque[int] | None = None
print(Model(deque=[1, 2, 3]).deque)
#> deque([1, 2, 3])
集合¶
set¶
允许 list、tuple、set、frozenset、deque 或生成器,并强制转换为 set。
当提供泛型参数时,适当的验证将应用于集合的所有项目。
typing.Set¶
处理方式与 set 相同。
from typing import Optional, Set
from pydantic import BaseModel
class Model(BaseModel):
simple_set: Optional[set] = None
set_of_ints: Optional[Set[int]] = None
print(Model(simple_set={'1', '2', '3'}).simple_set)
#> {'1', '2', '3'}
print(Model(simple_set=['1', '2', '3']).simple_set)
#> {'1', '2', '3'}
print(Model(set_of_ints=['1', '', '3']).set_of_ints)
#> {1, 2, 3}
from pydantic import BaseModel
class Model(BaseModel):
simple_set: set | None = None
set_of_ints: set[int] | None = None
print(Model(simple_set={'1', '2', '3'}).simple_set)
#> {'1', '2', '3'}
print(Model(simple_set=['1', '2', '3']).simple_set)
#> {'1', '2', '3'}
print(Model(set_of_ints=['1', '', '3']).set_of_ints)
#> {1, 2, 3}
frozenset¶
允许 list、tuple、set、frozenset、[deque][collections.deque] 或生成器,并强制转换为 [frozenset`][`deque][collections.deque] 或生成器,并强制转换为 [`frozenset`]。
当提供泛型参数时,适当的验证将应用于冻结集合的所有项目。
typing.FrozenSet¶
处理方式与 frozenset 相同。
from typing import FrozenSet, Optional
from pydantic import BaseModel
class Model(BaseModel):
simple_frozenset: Optional[frozenset] = None
frozenset_of_ints: Optional[FrozenSet[int]] = None
m1 = Model(simple_frozenset=['1', '2', '3'])
print(type(m1.simple_frozenset))
#> <class 'frozenset'>
print(sorted(m1.simple_frozenset))
#> ['1', '2', '3']
m2 = Model(frozenset_of_ints=['1', '2', '3'])
print(type(m2.frozenset_of_ints))
#> <class 'frozenset'>
print(sorted(m2.frozenset_of_ints))
#> [1, 2, 3]
from pydantic import BaseModel
class Model(BaseModel):
simple_frozenset: frozenset | None = None
frozenset_of_ints: frozenset[int] | None = None
m1 = Model(simple_frozenset=['1', '2', '3'])
print(type(m1.simple_frozenset))
#> <class 'frozenset'>
print(sorted(m1.simple_frozenset))
#> ['1', '2', '3']
m2 = Model(frozenset_of_ints=['1', '2', '3'])
print(type(m2.frozenset_of_ints))
#> <class 'frozenset'>
print(sorted(m2.frozenset_of_ints))
#> [1, 2, 3]
其他可迭代对象¶
typing.Sequence¶
这适用于当提供的值应满足 Sequence ABC 的要求,并且希望对容器中的值进行急切验证时。
请注意,当必须对容器的值进行验证时,容器的类型可能不会被保留,因为验证最终可能会替换值。
我们保证验证后的值将是一个有效的 typing.Sequence,但它可能与提供的类型不同(通常,它会变成一个 list)。
typing.Iterable¶
这适用于当提供的值可能是一个不应被消耗的可迭代对象时。
有关解析和验证的更多详细信息,请参见下面的无限生成器。
与 typing.Sequence 类似,我们保证验证结果将是一个有效的 typing.Iterable,但它可能与提供的类型不同。
特别是,即使提供了非生成器类型(如 list),类型为 typing.Iterable 的字段的验证后值将是一个生成器。
以下是使用 typing.Sequence 的简单示例:
from collections.abc import Sequence
from pydantic import BaseModel
class Model(BaseModel):
sequence_of_ints: Sequence[int]
print(Model(sequence_of_ints=[1, 2, 3, 4]).sequence_of_ints)
#> [1, 2, 3, 4]
print(Model(sequence_of_ints=(1, 2, 3, 4)).sequence_of_)
#> (, 2, 3, 4)
无限生成器¶
如果您有一个想要验证的生成器,您仍然可以使用上面描述的 Sequence。
在这种情况下,生成器将被消耗并作为列表存储在模型上,其值将根据 Sequence 的类型参数(例如 Sequence[int] 中的 int)进行验证。
但是,如果您有一个不希望被急切消耗的生成器(例如,无限生成器或远程数据加载器),您可以使用类型为 Iterable 的字段:
from collections.abc import Iterable
from pydantic import BaseModel
class Model(BaseModel):
infinite: Iterable[int]
def infinite_ints():
i = 0
while True:
yield i
i += 1
m = Model(infinite=infinite_ints())
print(m)
"""
infinite=ValidatorIterator(index=0, schema=Some(Int(IntValidator { strict: false })))
"""
for i in m.infinite:
print(i)
#> 0
#> 1
#> 2
#> 3
#> 4
#> 5
# 6
#> 7
#> 8
#> 9
#> 10
if i == 10:
break
Warning
在初始验证期间,Iterable 字段仅执行简单检查,确保提供的参数是可迭代的。
为了防止它被消耗,不会急切地执行生成值的验证。
尽管生成的值不会急切验证,但它们仍然在生成时进行验证,并在适当时会引发 ValidationError:
from collections.abc import Iterable
from pydantic import BaseModel, ValidationError
class Model(BaseModel):
int_iterator: Iterable[int]
def my_iterator():
yield 13
yield '27'
yield 'a'
m = Model(int_iterator=my_iterator())
print(next(m.int_iterator))
#> 13
print(next(m.int_iterator))
#> 27
try:
next(m.int_iterator)
except ValidationError as e:
print(e)
"""
1 validation error for ValidatorIterator
2
Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='a', input_type=str]
"""
映射类型¶
dict¶
使用 dict(v) 尝试转换字典。
from pydantic import BaseModel, ValidationError
class Model(BaseModel):
x: dict[str, int]
m = Model(x={'foo': 1})
print(m.model_dump())
#> {'x': {'foo': 1}}
try:
Model(x={'foo': '1'})
except ValidationError as e:
print(e)
"""
1 validation error for Model
x
Input should be a valid dictionary [type=dict_type, input_value='test', input_type=str]
"""
TypedDict¶
Note
这是 Python 3.8 起 Python 标准库的新功能。
由于 Python <3.12 中 typing.TypedDict 的限制,Python <3.12 需要 typing-extensions 包。
您需要从 typing_extensions 而不是 typing 导入 TypedDict,如果不这样做,将在构建时出现错误。
TypedDict 声明了一种字典类型,期望其所有实例都具有一定的键集,其中每个键都与一个类型一致的值相关联。
它与 dict 相同,但 Pydantic 将验证字典,因为键被注解了。
from typing_extensions import TypedDict
from pydantic import TypeAdapter, ValidationError
class User(Typed):
name: str
id: int
ta = TypeAdapter(User)
print(ta.validate_python({'name': 'foo', 'id': 1}))
#> {'name': 'foo', 'id': 1}
try:
ta.validate_python({'name': 'foo'})
except ValidationError as e:
print(e)
"""
1 validation error for User
id
Field required [type=missing, input_value={'name': 'foo'}, input_type=dict]
"""
from pydantic import TypeAdapter, ValidationError
class User(Typed):
name: str
id: int
ta = TypeAdapter(User)
print(ta.validate_python({'name': 'foo', 'id': 1}))
#> {'name': 'foo', 'id': 1}
try:
ta.validate_python({'name': 'foo'})
except ValidationError as e:
print(e)
"""
1 validation error for User
id
Field required [type=missing, input_value={'name': 'foo'}, input_type=dict]
"""
您可以定义 __pydantic_config__ 来更改从 TypedDict 继承的模型。
有关更多详细信息,请参见 ConfigDict API 参考。
from typing import Optional
from typing_extensions import TypedDict
from pydantic import ConfigDict, TypeAdapter, ValidationError
# `total=False` 表示键是非必需的
class UserIdentity(TypedDict, total=False):
name: Optional[str]
surname: str
class User(TypedDict):
__pydantic_config__ = ConfigDict(extra='forbid')
identity: UserIdentity
age: int
ta = TypeAdapter(User)
print(
ta.validate_python(
{'identity': {'name': 'Smith', 'surname': 'John'}, 'age': 37}
)
)
#> {'identity': {'name': 'Smith', 'surname': 'John'}, 'age': 37}
print(
ta.validate_python(
{'identity': {'name': None, 'surname': 'John'}, 'age': 37}
)
)
#> {'identity': {'name': None, 'surname': ''}, 'age': 37}
print(ta.validate_python({'identity': {}, 'age': 37}))
#> {'identity': {}, 'age': 37}
try:
ta.validate_python(
{'identity': {'name': ['Smith'], 'surname': 'John'}, 'age': 24}
)
except ValidationError as e:
print(e)
"""
1 validation error for User
identity.name
Input should be a valid string [type=string_type, input_value=['Smith'], input_type=list]
"""
try:
ta.validate_python(
{
'identity': {'name': 'Smith', 'surname': 'John'},
'age': '37',
'email': 'john.smith@me.com',
}
)
except ValidationError as e:
print(e)
"""
1 validation error for User
email
Extra inputs are not permitted [type=extra_forbidden, input_value='john.smith@', input_type=str]
"""
from typing_extensions import TypedDict
from pydantic import ConfigDict, TypeAdapter, ValidationError
# `total=False` 表示键是非必需的
class UserIdentity(TypedDict, total=False):
name: str | None
surname: str
class User(TypedDict):
__pydantic_config__ = ConfigDict(extra='forbid')
identity: UserIdentity
age: int
ta = TypeAdapter(User)
print(
ta.validate_python(
{'identity': {'name': 'Smith', 'surname': 'John'}, 'age': 37}
)
)
#> {'identity': {'name': 'Smith', 'surname': 'John'}, 'age': 37}
print(
ta.validate_python(
{'identity': {'name': None, 'surname': 'John'}, 'age': 37}
)
)
#> {'identity': {'name': None, 'surname': ''}, 'age': 37}
print(ta.validate_python({'identity': {}, 'age': 37}))
#> {'identity': {}, 'age': 37}
try:
ta.validate_python(
{'identity': {'name': ['Smith'], 'surname': 'John'}, 'age': 24}
)
except ValidationError as e:
print(e)
"""
1 validation error for User
identity.name
Input should be a valid string [type=string_type, input_value=['Smith'], input_type=list]
"""
try:
ta.validate_python(
{
'identity': {'name': 'Smith', 'surname': 'John'},
'age': '37',
'email': 'john.smith@me.com',
}
)
except ValidationError as e:
print(e)
"""
1 validation error for User
email
Extra inputs are not permitted [type=extra_forbidden, input_value='john.smith@', input_type=str]
"""
from typing import TypedDict
from pydantic import ConfigDict, TypeAdapter, ValidationError
# `total=False` 表示键是非必需的
class UserIdentity(TypedDict, total=False):
name: str | None
surname: str
class User(TypedDict):
__pydantic_config__ = ConfigDict(extra='forbid')
identity: UserIdentity
age: int
ta = TypeAdapter(User)
print(
ta.validate_python(
{'identity': {'name': 'Smith', 'surname': 'John'}, 'age': 37}
)
)
#> {'identity': {'name': 'Smith', 'surname': 'John'}, 'age': 37}
print(
ta.validate_python(
{'identity': {'name': None, 'surname': 'John'}, 'age': 37}
)
)
#> {'identity': {'name': None, 'surname': ''}, 'age': 37}
print(ta.validate_python({'identity': {}, 'age': 37}))
#> {'identity': {}, 'age': 37}
try:
ta.validate_python(
{'identity': {'name': ['Smith'], 'surname': 'John'}, 'age': 24}
)
except ValidationError as e:
print(e)
"""
1 validation error for User
identity.name
Input should be a valid string [type=string_type, input_value=['Smith'], input_type=list]
"""
try:
ta.validate_python(
{
'identity': {'name': 'Smith', 'surname': 'John'},
'age': '37',
'email': 'john.smith@me.com',
}
)
except ValidationError as e:
print(e)
"""
1 validation error for User
email
Extra inputs are not permitted [type=extra_forbidden, input_value='john.smith@', input_type=str]
"""
可调用对象¶
有关解析和验证的更多详细信息,请参见下文
字段也可以是 Callable 类型:
from typing import Callable
from pydantic import BaseModel
class Foo(BaseModel):
callback: Callable[[int], int]
m = Foo(callback=lambda x: x)
print(m)
#> callback=<function <lambda> at 0x0123456789ab>
from collections.abc import Callable
from pydantic import BaseModel
class Foo(BaseModel):
callback: Callable[[int], int]
m = Foo(callback=lambda x: x)
print(m)
#> callback=<function <lambda> at 0x0123456789ab>
Warning
可调用字段仅执行简单检查,确保参数是可调用的; 不执行参数、其类型或返回类型的验证。
IP 地址类型¶
ipaddress.IPv4Address:通过将值传递给IPv4Address(v)来使用类型本身进行验证。ipaddress.IPv4Interface:通过将值传递给IPv4Address(v)来使用类型本身进行验证。ipaddress.IPv4Network:通过将值传递给IPv4Network(v)来使用类型本身进行验证。ipaddress.IPv6Address:通过将值传递给IPv6Address(v)来使用类型本身进行验证。ipaddress.IPv6Interface:通过将值传递给IPv6Interface(v)来使用类型本身进行验证。ipaddress.IPv6Network:通过将值传递给IPv6Network(v)来使用本身进行验证。
有关其他自定义 IP 地址类型,请参见网络类型。
UUID¶
对于 UUID,Pydantic 尝试通过将值传递给 UUID(v) 来使用类型本身进行验证。
对于 bytes 和 bytearray,有回退到 UUID(bytes=v)。
如果您想约束 UUID 版本,可以检查以下类型:
联合¶
Pydantic 对联合验证有广泛的支持,typing.Union 和 Python 3.10 的管道语法(A | B)都支持。
有关更多信息,请阅读概念文档中的联合部分。
type¶
Pydantic 支持使用 type[T] 来指定字段只能接受是 T 子类的类(而不是实例)。
from pydantic import BaseModel, ValidationError
class Foo:
pass
class Bar(Foo):
pass
class Other:
pass
class SimpleModel(BaseModel):
just_subclasses: type[Foo]
SimpleModel(just_subclasses=Foo)
SimpleModel(just_subclasses=Bar)
try:
SimpleModel(just_subclasses=Other)
except ValidationError as e:
print(e)
"""
1 validation error for SimpleModel
just_subclasses
Input should be a subclass of Foo [type=is_subclass_of, input_value=<class '__main__.Other'>, input_type=type]
"""
您也可以使用 type 来指定允许任何类。
from pydantic import BaseModel, ValidationError
class Foo:
pass
class LenientSimpleModel(BaseModel):
any_class_goes: type
LenientSimpleModel(any_class_goes=int)
LenientSimpleModel(any_class_goes=Foo)
try:
LenientSimpleModel(any_class_goes=Foo())
except ValidationError as e:
print(e)
"""
1 validation error for LenientSimpleModel
any_class_goes
Input should be a type [type=is_type, input_value=<__main__.Foo object at 0x0123456789ab>, input_type=Foo]
"""
typing.TypeVar¶
TypeVar 支持无约束、有约束或有边界。
from typing import TypeVar
from pydantic import BaseModel
Foobar = TypeVar('Foobar')
BoundFloat = TypeVar('BoundFloat', bound=float)
IntStr = TypeVar('IntStr', int, str)
class Model(BaseModel):
a: Foobar # 相当于 ": Any"
b: BoundFloat # 相当于 ": float"
c: IntStr # 相当于 ": Union[int, str]"
print(Model(a=[1], b=4.2, c='x'))
#> a=[1] b=4.2 c='x'
# a 可能为 None
print(Model(a=None, b=1, c=1))
#> a=None b=1.0 c=1
None 类型¶
None、type(None) 或 Literal[None] 根据类型规范都是等效的。
只允许 None 值。
字符串¶
所有其他类型都会导致错误。
字符串不是序列
虽然 str 的实例从类型检查器的角度来看是 Sequence[str] 协议的有效实例,但这通常不是预期的,并且是常见的错误来源。
因此,如果您尝试将 str 或 bytes 实例传递到类型为 Sequence[str] 或 Sequence[bytes] 的字段中,Pydantic 会引发 ValidationError:
from collections.abc import Sequence
from typing import Optional
from pydantic import BaseModel, ValidationError
class Model(BaseModel):
sequence_of_strs: Optional[Sequence[str]] = None
sequence_of_bytes: Optional[Sequence[bytes]] = None
print(Model(sequence_of_strs=['a', 'bc']).sequence_of_strs)
#> ['a', 'bc']
print(Model(sequence_of_strs=('a', 'bc')).sequence_of_strs)
#> ('a', 'bc')
print(Model(sequence_of_bytes=[b'a', b'bc']).sequence_of_bytes)
#> [b'a', b'bc']
print(Model(sequence_of_bytes=(b'a', b'bc')).sequence_of_bytes)
#> (b'a', b'bc')
try:
Model(sequence_of_strs='abc')
except ValidationError as e:
print(e)
"""
1 validation error for Model
sequence_of_strs
'str' instances are not allowed as a Sequence value [type=sequence_str, input_value='abc', input_type=str]
"""
try:
Model(sequence_of_bytes=b'abc')
except ValidationError as e:
print(e)
"""
1 validation error for Model
sequence_of_bytes
'bytes' instances are not allowed as a Sequence value [type=sequence_str, input_value=b'abc', input_type=bytes]
"""
from collections.abc import Sequence
from pydantic import BaseModel, ValidationError
class Model(BaseModel):
sequence_of_strs: Sequence[str] | None = None
sequence_of_bytes: Sequence[bytes] | None = None
print(Model(sequence_of_strs=['a', 'bc']).sequence_of_strs)
#> ['a', 'bc']
print(Model(sequence_of_strs=('a', 'bc')).sequence_of_strs)
#> ('a', 'bc')
print(Model(sequence_of_bytes=[b'a', b'bc']).sequence_of_bytes)
#> [b'a', b'bc']
print(Model(sequence_of_bytes=(b'a', b'bc')).sequence_of_bytes)
#> (b'a', b'bc')
try:
Model(sequence_of_strs='abc')
except ValidationError as e:
print(e)
"""
1 validation error for Model
sequence_of_strs
'str' instances are not allowed as a Sequence value [type=sequence_str, input_value='abc', input_type=str]
"""
try:
Model(sequence_of_bytes=b'abc')
except ValidationError as e:
print(e)
"""
1 validation error for Model
sequence_of_bytes
'bytes' instances are not allowed as a Sequence value [type=sequence_str, input_value=b'abc', input_type=bytes]
"""
字节¶
bytes 按原样接受。bytearray 使用 bytes(v) 转换。str 使用 v.encode() 转换。int、float 和 Decimal 使用 str(v).encode() 强制转换。有关更多详细信息,请参见 ByteSize。
typing.Literal¶
Pydantic 支持使用 typing.Literal 作为一种轻量级方式来指定字段只能接受特定的字面值:
from typing import Literal
from pydantic import BaseModel, ValidationError
class Pie(BaseModel):
flavor: Literal['apple', 'pumpkin']
Pie(flavor='apple')
Pie(flavor='pumpkin')
try:
Pie(flavor='cherry')
except ValidationError as e:
print(str(e))
"""
1 validation error for Pie
flavor
Input should be 'apple' or 'pumpkin' [type=literal_error, input_value='cherry', input_type=str]
"""
这种字段类型的一个好处是,它可以用于检查与一个或多个特定值的相等性,而无需声明自定义验证器:
from typing import ClassVar, Literal, Union
from pydantic import BaseModel, ValidationError
class Cake(BaseModel):
kind: Literal['cake']
required_utensils: ClassVar[list[str]] = ['fork', 'knife']
class IceCream(BaseModel):
kind: Literal['icecream']
required_utensils: ClassVar[list[str]] = ['spoon']
class Meal(BaseModel):
dessert: Union[Cake, IceCream]
print(type(Meal(dessert={'kind': 'cake'}).dessert).__name__)
#> Cake
print(type(Meal(dessert={'kind': 'icecream'}).dessert).__name__)
#> IceCream
try:
Meal(dessert={'kind': 'pie'})
except ValidationError as e:
print(str(e))
"""
2 validation errors for Meal
dessert.Cake.kind
Input should be 'cake' [type=literal_error, input_value='pie', input=str]
dessert.IceCream.kind
Input should be 'icecream' [type=literal_error, input_value='pie', input_type=str]
"""
通过带注解的 Union 中的正确排序,您可以使用它来解析递减特异性的类型:
from typing import Literal, Optional, Union
from pydantic import BaseModel
class Dessert(BaseModel):
kind: str
class Pie(Dessert):
kind: Literal['']
flavor: Optional[str]
class ApplePie(Pie):
flavor: Literal['apple']
class PumpkinPie(Pie):
flavor: Literal['pumpkin']
class Meal(BaseModel):
dessert: Union[ApplePie, PumpkinPie, Pie, Dessert]
print(type(Meal(dessert={'kind': 'pie', 'flavor': 'apple'}).dessert).__name__)
#> ApplePie
print(type(Meal(dessert={'kind': 'pie', 'flavor': 'pumpkin'}).dessert).__name__)
#> PumpkinPie
print(type((dessert={'kind': 'pie'}).dessert).__name__)
#> Dessert
print(type(Meal(dessert={'kind': 'cake'}).dessert).__name__)
#> Dessert
typing.Any¶
允许任何值,包括 None。
typing.Hashable¶
- 从 Python 中,支持任何通过
isinstance(v, Hashable)检查的数据。 - 从 JSON 中,首先通过
Any验证器加载数据,然后使用isinstance(v, Hashable)检查数据是否可哈希。
typing.Annotated¶
允许根据 PEP-593 使用任意元数据包装另一种类型。Annotated 提示可能包含对 Field 函数的单个调用,但否则额外的元数据将被忽略,并使用根类型。
typing.Pattern¶
将导致输入值被传递给 re.compile(v) 以创建正则表达式模式。
pathlib.Path¶
通过将值传递给 Path(v) 来使用类型本身进行验证。