Pydantic поддерживает множество распространенных типов из стандартной библиотеки Python. Если вам нужна более строгая обработка, см. Strict Types , в том числе, если вам нужно ограничить разрешенные значения (например, потребовать положительное int
).
логические значения¶
Стандартное поле bool
вызовет ValidationError
, если значение не является одним из следующих:
- Допустимое логическое значение (т. е.
True
илиFalse
), - Целые числа
0
или1
, str
, которая при преобразовании в нижний регистр является одной из'0', 'off', 'f', 'false', 'n', 'no', '1', 'on', 't', 'true', 'y', 'yes'
bytes
, которые действительны в соответствии с предыдущим правилом при декодировании вstr
!!! Примечание. Если вам нужна более строгая логическая логика (например, поле, которое допускает только 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
int
илиfloat
; предполагается как время Unix, т.е. секунды (если >=-2e10
и <=2e10
) или миллисекунды (если <-2e10
или >2e10
) с 1 января 1970 г.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(+02:30))} """
datetime.date
¶
-
Поля
date
будут принимать значения типа:date
; существующий объектdate
int
илиfloat
; обрабатывается так же, как описано дляdatetime
вышеstr
; принимаются следующие форматы:YYYY-MM-DD
int
или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())
>¶
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())
>¶
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 для временной разницы)
from datetime import timedelta
from pydantic import BaseModel
class Model(BaseModel): td: timedelta = None
m = Model(td='P3DT12H30M5S')
print(m.model_dump())
>¶
Типы номеров¶
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_extensions import Annotated
from pydantic import BaseModel, PlainSerializer
class Model(BaseModel): x: Decimal y: Annotated[ Decimal, PlainSerializer( lambda x: float(x), return_type=float, when_used='json' ), ]
my_model = Model(x=Decimal('1.1'), y=Decimal('2.1'))
print(my_model.model_dump()) # (1)!
>¶
print(my_model.model_dump(mode='json')) # (2)!
>¶
print(my_model.model_dump_json()) # (3)!
>¶
-
При использовании
model_dump
обаx
иy
остаются экземплярами типаDecimal
. - При использовании
model_dump
сmode='json'
x
сериализуется какstring
, аy
сериализуется какfloat
из-за примененного пользовательского сериализатора. - Используя
model_dump_json
,x
сериализуется какstring
, аy
сериализуется какfloat
из-за применения специального сериализатора.
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 'pear' or 'banana' [type=enum, input_value='other', input_type=str]
"""
Списки и кортежи¶
list
¶
Разрешает list
, tuple
, set
, frozenset
, deque
или генераторы и приводит к list
. Если указан общий параметр, соответствующая проверка применяется ко всем элементам списка.
typing.List
¶
Обрабатывается так же, как list
выше.
from typing import List, 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_ints)
#> [1, 2, 3]
tuple
¶
Разрешает list
, tuple
, set
, frozenset
, deque
или генераторы и приводит к tuple
. Если предоставлены общие параметры, соответствующая проверка применяется к соответствующим элементам кортежа.
typing.Tuple
¶
Обрабатывается так же, как tuple
выше.
from typing import Optional, Tuple
from pydantic import BaseModel
class Model(BaseModel):
simple_tuple: Optional[tuple] = None
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(NamedTuple):
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]
"""
Дек¶
deque
¶
Разрешает 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])
Наборы¶
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', '2', '3']).set_of_ints)
#> {1, 2, 3}
frozenset
¶
Разрешает list
, tuple
, set
, frozenset
, 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]
Другие итерации¶
typing.Sequence
¶
Это предназначено для использования, когда предоставленное значение должно соответствовать требованиям Sequence
ABC и желательно выполнить быструю проверку значений в контейнере. Обратите внимание: если необходимо выполнить проверку значений контейнера, тип контейнера может не сохраниться, поскольку проверка может привести к замене значений. Мы гарантируем, что проверенное значение будет допустимым typing.Sequence
, но оно может иметь тип, отличный от указанного (обычно это list
).
typing.Iterable
¶
Это предназначено для использования, когда предоставленное значение может быть итерацией, которую не следует использовать. См. «Бесконечные генераторы» ниже для получения более подробной информации о синтаксическом анализе и проверке. Как и в случае с typing.Sequence
, мы гарантируем, что проверенный результат будет действительным typing.Iterable
, но его тип может отличаться от указанного. В частности, даже если указан тип, не являющийся генератором, например list
, значение поля типа typing.Iterable
после проверки будет генератором.
Вот простой пример использования typing.Sequence
:
from typing import Sequence
from pydantic import BaseModel
class Model(BaseModel):
sequence_of_ints: Sequence[int] = None
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_ints)
#> (1, 2, 3, 4)
Бесконечные генераторы¶
Если у вас есть генератор, который вы хотите проверить, вы все равно можете использовать Sequence
как описано выше. В этом случае генератор будет использован и сохранен в модели в виде списка, а его значения будут проверены на соответствие параметру типа Sequence
(например, int
в Sequence[int]
).
Однако если у вас есть генератор, который вы не хотите активно использовать (например, бесконечный генератор или удаленный загрузчик данных), вы можете использовать поле типа Iterable
:
from typing 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
!!! предупреждение. Во время первоначальной проверки Iterable
поля выполняют только простую проверку того, что предоставленный аргумент является итеративным. Чтобы предотвратить его использование, проверка полученных значений не выполняется с нетерпением.
Хотя полученные значения не проверяются с особой тщательностью, они все равно проверяются при получении и при необходимости вызывают ValidationError
во время получения:
from typing 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)
используется для попытки конвертировать словарь. см. typing.Dict
ниже для ограничений подтипа.
from pydantic import BaseModel, ValidationError
class Model(BaseModel):
x: dict
m = Model(x={'foo': 1})
print(m.model_dump())
#> {'x': {'foo': 1}}
try:
Model(x='test')
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]
"""
typing.Dict
¶
from typing import Dict
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]
"""
ТипедДикт¶
!!! note Примечание. Это новая функция стандартной библиотеки Python, начиная с версии Python 3.8. Из-за ограничений в typing.TypedDict до версии 3.12 для Python <3.12 требуется пакет typing-extensions . Вам нужно будет импортировать TypedDict
из typing_extensions
вместо typing
, и если вы этого не сделаете, вы получите ошибку времени сборки.
TypedDict
объявляет тип словаря, который ожидает, что все его экземпляры будут иметь определенный набор ключей, где каждый ключ связан со значением согласованного типа.
Это то же самое, что и dict
, но Pydantic проверит словарь, поскольку ключи аннотированы.
from typing_extensions import TypedDict
from pydantic import TypeAdapter, ValidationError
class User(TypedDict):
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 typed-dict
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` means keys are non-required
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': 'John'}, '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 typed-dict
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 typed-dict
email
Extra inputs are not permitted [type=extra_forbidden, input_value='john.smith@me.com', 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>
!!! предупреждение. Вызываемые поля выполняют только простую проверку возможности вызова аргумента; проверка аргументов, их типов или возвращаемого типа не выполняется.
Типы 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)
. Существует запасной вариант UUID(bytes=v)
для bytes
и bytearray
.
Если вы хотите ограничить версию UUID, вы можете проверить следующие типы:
UUID1
: требуется UUID версии 1.UUID3
: требуется UUID версии 3.UUID4
: требуется UUID версии 4.UUID5
: требуется UUID версии 5.
Союз¶
Pydantic имеет обширную поддержку проверки объединения, поддерживаются как typing.Union
, так и синтаксис канала Python 3.10 ( A | B
). Подробнее читайте в разделе Unions
документации по концепциям.
Type
и TypeVar
¶
type
¶
Pydantic поддерживает использование type[T]
для указания того, что поле может принимать только классы (не экземпляры), которые являются подклассами T
.
[typing.Type
. Введите ][]¶
Обрабатывается так же, как и type
выше.
from typing import Type
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 typing import 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 # equivalent of ": Any"
b: BoundFloat # equivalent of ": float"
c: IntStr # equivalent of ": Union[int, str]"
print(Model(a=[1], b=4.2, c='x'))
#> a=[1] b=4.2 c='x'
# a may be None
print(Model(a=None, b=1, c=1))
#> a=None b=1.0 c=1
Нет Типы¶
None
, type(None)
или Literal[None]
эквивалентны в соответствии со спецификацией типизации . Допускается только значение None
.
Струны¶
str
: строки принимаются как есть. bytes
и bytearray
преобразуются с помощью v.decode()
. Enum s inheriting from
str, are converted using
v.value`. Все остальные типы вызывают ошибку.
!!! предупреждение «Строки не являются последовательностями»
While instances of `str` are technically valid instances of the `Sequence[str]` protocol from a type-checker's point of
view, this is frequently not intended as is a common source of bugs.
As a result, Pydantic raises a `ValidationError` if you attempt to pass a `str` or `bytes` instance into a field of type
`Sequence[str]` or `Sequence[bytes]`:
from typing import Optional, Sequence
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]
"""
Байты¶
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, List, 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_type=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['pie']
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(Meal(dessert={'kind': 'pie'}).dessert).__name__)
#> Dessert
print(type(Meal(dessert={'kind': 'cake'}).dessert).__name__)
#> Dessert
typing.Any
¶
Допускается любое значение, включая None
.
typing.Annotated
¶
Позволяет обернуть другой тип произвольными метаданными согласно PEP-593 . Подсказка Annotated
может содержать один вызов функции Field
, но в противном случае дополнительные метаданные игнорируются и используется корневой тип.
typing.Pattern
¶
Приведёт к передаче входного значения в re.compile(v)
для создания шаблона регулярного выражения.
pathlib.Path
¶
Просто использует сам тип для проверки, передавая значение в Path(v)
.
本文总阅读量次