Pydanticのdataclassを試す

Pydanticは、Pythonでデータの検証(バリデーション)を実装するためのライブラリです。

基本的な入力型の検証はTypingを記述するだけで実装できるということで、最近の型ヒントを記述するPythonコードと組み合わせて使うことを想定しています。 docs.pydantic.dev 一方、Pythonには標準モジュールで、 dataclasses というのがあります。 docs.python.org dataclassesモジュールに含まれるdataclassデコレータを使うと、型ヒントを使って簡単にデータ型を記述できます。

Pydanticはこのdataclassと互換性のある機能を提供しているので、これを試してみます。

dataclassesでの記述

main.py:

from dataclasses import dataclass

@dataclass
class User:
    id: int
    name: str

user1 = User(id=123, name="foo")
print(user1)
user2 = User(id="abc", name="bar")
print(user2)

意図的に user2.id はint型ではない文字列を指定しています。実行結果はこうなります。

$ python main.py
User(id=123, name='foo')
User(id='abc', name='bar')

標準モジュールのdataclassで作成したクラスでは、特にバリデーションの処理はないので、Pythonのコードとして実行可能であればエラーは発生しません。

ただし、mypyで型チェックをしてみると、型の不正を検出できます。

$ mypy main.py
main.py:10: error: Argument "id" to "User" has incompatible type "str"; expected "int"  [arg-type]
Found 1 error in 1 file (checked 1 source file)

pydantic.dataclassesでの記述

dataclassをPydanticのものに切り替えてみます。 importの1行だけ変更しました。

main.py:

from pydantic.dataclasses import dataclass  # ここだけ変更

@dataclass
class User:
    id: int
    name: str

user1 = User(id=123, name="foo")
print(user1)
user2 = User(id="abc", name="bar")
print(user2)

実行結果はこうなります。

$ python main.py
User(id=123, name='foo')
Traceback (most recent call last):
  File "/home/vagrant/tmp/pydantic/main.py", line 10, in <module>
    user2 = User(id="abc", name="bar")
            ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vagrant/tmp/pydantic/venv/lib/python3.12/site-packages/pydantic/_internal/_dataclasses.py", line 121, in __init__
    s.__pydantic_validator__.validate_python(ArgsKwargs(args, kwargs), self_instance=s)
pydantic_core._pydantic_core.ValidationError: 1 validation error for User
id
  Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='abc', input_type=str]
    For further information visit https://errors.pydantic.dev/2.10/v/int_parsing

pydanticのValidationErrorが発生しました。

標準モジュールのdataclassesと同様の書き方で、pydanticをすぐに導入できるのは興味深いです。

pydanticのドキュメントには、BaseModelを継承するのとdataclassを使うのでは、機能的な差があるとも書かれているので、利用する際には気を付けておいたほうが良さそうです。

Dataclasses - Pydantic