dataclassデコレータとは?
dataclassデコレータとは、Pythonのクラスをより便利にしてくれるもの。
@dataclass
をクラスに付与することで使えるようになる。
公式ドキュメントはこちら。
dataclasses --- データクラス
ソースコード: Lib/dataclasses.py このモジュールは、__init__() や__init__() のような special method を生成し、ユーザー定義のクラスに自動的に追加するデコレータや関数を提供します。この...
dataclassデコレータのメリット
- 初期化メソッドや等価比較メソッドを自動生成してくれる
- デバッグ時にクラスの中身が確認しやすい
- データをイミュータブル(後から書き換え不可)にすることができる
①初期化メソッドや等価比較メソッドを自動で生成してくれる
クラスを自作するとき、以下のような__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でクラス使うなら、絶対使うべき