LoginSignup
1
0

More than 1 year has passed since last update.

pydanticの動作変更 [BaseConfig]

Last updated at Posted at 2022-10-03

はじめに

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)

参考文献

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0