【Python】dataclassデコレータとは

python-logo Python

dataclassデコレータとは?

dataclassデコレータとは、Pythonのクラスをより便利にしてくれるもの。

@dataclassをクラスに付与することで使えるようになる。

公式ドキュメントはこちら。

dataclasses --- データクラス
ソースコード: Lib/dataclasses.py このモジュールは、__init__() や__init__() のような special method を生成し、ユーザー定義のクラスに自動的に追加するデコレータや関数を提供します。この...

dataclassデコレータのメリット

  1. 初期化メソッドや等価比較メソッドを自動生成してくれる
  2. デバッグ時にクラスの中身が確認しやすい
  3. データをイミュータブル(後から書き換え不可)にすることができる

①初期化メソッドや等価比較メソッドを自動で生成してくれる

クラスを自作するとき、以下のような__init__()メソッドを自分で書くことが多い。

# 名前データを持つユーザークラス
class User:
    name: str

    def __init__(self, name: str):
        self.name = name

これを、dataclassデコレータを利用することにより省略することができる。

from dataclasses import dataclass

@dataclass
class User:
    name: str

また、このとき__eq__()メソッドも自動で生成されているため
オブジェクトの等価比較メソッドも自分で書く必要はなくなる。

※クラスの中身まで含めてしっかり等価比較する場合は、__eq__()を用意する必要がある

②デバッグ時にクラスの中身を確認しやすい

個人的にはこの機能が一番大きなメリットである。

以下のように、インスタンスをprint関数で出力すると
インスタンスの名前とアドレスが出力されてしまい、中身のnameの値を確認することができない。

class User:
    name: str

    def __init__(self, name: str):
        self.name = name


user: User = User("hoge")
print(user)
# nameの値が確認できない
$ python main.py
<__main__.User object at 0x10ab3cad0>

この問題が、dataclassデコレータを利用することで解消される。

from dataclasses import dataclass

@dataclass
class User:
    name: str

user: User = User("hoge")
print(user)
# nameに「hoge」が入っていることが確認できる
$ python main.py
User(name='hoge')

これはdataclassデコレータによって
Pythonの特殊メソッド__repr__()が自動生成されているためである。

③データをイミュータブルにすることができる

可読性の高いコードの鉄則として、
「一度作った変数やオブジェクトの中身を変更しない」というものがある。

dataclassデコレータのfrozen=Trueを利用することで、この仕組みを強制することができる。

@dataclass(frozen=True)を付与したクラスの内部にあるnameという変数を書き換えるようなコードを書く。

from dataclasses import dataclass


@dataclass(frozen=True)
class User:
    name: str


# データを初期化
user: User = User("hoge")
print(user)

# 名前を書き換えようとする
user.name = "fuga"

print(user)

これを実行してみると、以下のようにエラーが発生するようになった。

中身の書き換えが不可能になっていることが分かる。

$ python main.py
User(name='hoge')
Traceback (most recent call last):
  File "/Users/username/main.py", line 14, in <module>
    user.name = "fuga"
    ^^^^^^^^^
  File "<string>", line 4, in __setattr__
dataclasses.FrozenInstanceError: cannot assign to field 'name'

まとめ

  • いつも書く特殊メソッドの記述を省略できる
  • デバッグしやすくなる
  • 比較メソッドの自動生成やイミュータブル機能により、バグが混入しにくくなる
  • オブジェクト指向を理解していてPythonでクラス使うなら、絶対使うべき
タイトルとURLをコピーしました