はじめに
pythonは動的な型推論を行うがpydanticを使用することで型検証が可能である。しかし,作成時は型検証を行うが再代入時には型検証が行われない。この挙動を変更するにはBaseConfig
を使用する。
TL;DR
-
pydantic.BaseConfig
による動作の詳細設定が可能-
validate_assignment
: 再代入時の型検証 -
allow_mutation
,frozen
: イミュータブル化 -
extra
: 宣言以外のデータが入力された場合の設定
-
上記以外の設定項目は公式ドキュメントを参照
クラスの設定 pydantic.BaseConfig
BaseConfigには下記2つの記述方法がある。ここでは1つ目の記述で統一する。
# パターン1
class User_1(pydantic.BaseModel):
id: int
name: str
class Config:
validate_assignment = True
frozen = True
# パターン2
class User_2(
pydantic.BaseModel,
validate_assignment=True,
frozen=True,
):
id: int
name: str
パターン2の場合, pydantic.BaseConfig
のデフォルト値が取得できなくなる。
(取得できないデフォルト値を使用する場合でも正常に動作する)
再代入時の型検証 validate_assignment
再代入時にも型検証を実施したい場合,validate_assignment = True
を設定(デフォルト: False
)
class ValidateAssignmentModel(pydantic.BaseModel):
id: int
class Config:
validate_assignment = True
user = ValidateAssignmentModel(id=0)
print(f"{user = }")
user.id = 10
print(f"{user = }")
try:
user.id = None
except pydantic.ValidationError as e:
print("user.id = None = ")
print(f"{type(e).__name__}: {e}")
# user = ValidateAssignmentModel(id=0, name='abc')
# user = ValidateAssignmentModel(id=10, name='abc')
# user.id = None =
# ValidationError: 1 validation error for ValidateAssignmentModel
# id
# none is not an allowed value (type=type_error.none.not_allowed)
イミュータブル化 allow_mutation
, frozen
クラスをイミュータブル化したい場合,allow_mutation = False
もしくはfroze = True
を設定(デフォルト: allow_mutation = True
, froze = False
)
クラス自体がイミュータブルになるだけなのでミュータブルな変数をイミュータブルにすることはない。
class NotAllowMutationModel(pydantic.BaseModel):
a: str
b: dict
class Config:
allow_mutation = False
# `allow_mutation = False` or `frozen = True`
not_allow_mutation = NotAllowMutationModel(a="hello", b={"apple": "pear"})
try:
not_allow_mutation.a = "different"
except TypeError as e:
print("not_allow_mutation.a = 'different' = ")
print(f"{type(e).__name__}: {e}")
print(f'{not_allow_mutation.a = }')
print(f'{not_allow_mutation.b = }')
not_allow_mutation.b["apple"] = "grape"
print(f'{not_allow_mutation.b = }')
# not_allow_mutation.a = 'different' =
# TypeError: "NotAllowMutationModel" is immutable and does not support item assignment
# not_allow_mutation.a = 'hello'
# not_allow_mutation.b = {'apple': 'pear'}
# not_allow_mutation.b = {'apple': 'grape'}
変数b
はミュータブルな辞書型のため,クラスをイミュータブル化しても参照先の変更は保証されない。
宣言以外のデータが入力された場合の設定 extra
宣言以外のデータが入力された場合の動作設定項目は下記3つある。上から下にいくにつれて制限が強くなる。
宣言以外のデータが入力されたときにエラーが出力されるのはExtra.forbid
のみ。
Extra.allow
Extra.ignore
Extra.forbid
class ExtraAllowModel(pydantic.BaseModel):
a: str
class Config:
extra = pydantic.Extra.allow
class ExtraIgnoreModel(pydantic.BaseModel):
a: str
class Config:
extra = pydantic.Extra.ignore
class ExtraForbidModel(pydantic.BaseModel):
a: str
class Config:
extra = pydantic.Extra.forbid
print(f"{ExtraAllowModel(a='spam', b='oh no') = }")
print(f"{ExtraIgnoreModel(a='spam', b='oh no') = }")
try:
ExtraForbidModel(a="spam", b="oh no")
except pydantic.ValidationError as e:
print("ExtraForbidModel(a='spam', b='oh no') = ")
print(f"{type(e).__name__}: {e}")
# ExtraAllowModel(a='spam', b='oh no') = ExtraAllowModel(a='spam', b='oh no')
# ExtraIgnoreModel(a='spam', b='oh no') = ExtraIgnoreModel(a='spam')
# ExtraForbidModel(a='spam', b='oh no') =
# ValidationError: 1 validation error for ExtraForbidModel
# b
# extra fields not permitted (type=value_error.extra)