dataclassのおさらいとデータクラス変換の活用
データクラス(dataclass)ではないがそのように振る舞うクラスの型チェックのために、Python 3.11ではデータクラス変換(dataclass_transform)が導入されました。これにより、特別なプラグインなどを必要とせずに、dataclassのようなクラスであることを静的型チェックツールに伝えることができます。
dataclassとは?
dataclass_transformの意義に入る前に、まずはdataclassについておさらいしましょう。dataclassは、Python 3.7で導入された、データ格納のためのクラスのデコレータです(デコレータについては第1回を参照してください)。@dataclassでデコレートされたクラスや関数には、データ格納用として静的型チェックツールに認識されるほか、さまざまな関数が自動生成されるなどのメリットが生まれます。以下のリストでは、Personクラスに引数付きの__init__関数、__eq__関数、__repr__関数などが生成され、クラス自体にフィールドを2個記述するだけで引数付きコンストラクタ、インスタンスの内容での比較、形式化された表示などが利用できるようになります。
from dataclasses import dataclass
@dataclass
class Person:
name: str
age: int
# 引数付きのコンストラクタ
p = Person(name = "Nao", age = 60)
# __eq__関数の生成で内容の比較が可能
print(p == Person(name = "Nao", age = 60)) # 実行結果:True
# __repr__関数の生成で内容の表示が可能
print(p) # 実行結果:Person(name='Nao', age=60)
データクラス変換
このようにdataclassは便利ですが、これはあくまでも自前でデータクラスを実装するときの話です。Djangoなどの実装する独自のモデルクラスは、あくまでもデータクラスライクというだけで、そのままでは静的型チェックは働きません。そこで、そういったものでも静的型チェックツールの恩恵を受けやすくするように、データクラス変換(typing.dataclass_transform)が導入されました。
@dataclass_transformデコレータをクラスや関数に付与すると、静的型チェックツールはそれが@dataclassでデコレートされたものと同様に振る舞うというように解釈します。これにより、特別なプラグインなどを必要とせずに静的型チェックのメリットを受けられるようになります。
以下のリストでは、@dataclass_transform()デコレータを付与されたBaseDataクラスが@dataclassと同様に振る舞うものとして、それを継承するPersonクラスにおいても引数付きのコンストラクタが存在する、というように静的型チェックツールは判断します。
from typing import dataclass_transform
@dataclass_transform() (1)
class BaseData:
pass
class Person(BaseData): (2)
name: str
birth: int
c1 = Person() # mypyでMissing positional argumentsのエラー
c2 = Person("Nao", 1970)
c3 = Person("Yamauchi") # mypyでMissing positional argumentsのエラー
2個のフィールドのための引数が指定されているもの以外は、mypyによるチェックではMissing positional argumentsのエラーとなります。もちろん、実際に引数付きのコンストラクタが定義されているわけではないので、実行時にはc2の宣言でエラーになります。
@dataclassにはよらない独自のデータクラスでも、静的型チェックツールの恩恵を受けやすくなるので、ライブラリ製作者の間で利用が進んでいくと思われます。
まとめ
今回は、Python 3.10以降の新機能のうち、Python 3.11で導入された可変長ジェネリクス、Self型、改良されたTypedDict、文字列リテラル型、データクラス変換を紹介しました。
次回は、型関連の機能としていよいよPython 3.12でサポートされたジェネリクスのための新しい型引数構文、**kwargsのより精密な型付け、静的型付けのためのオーバーライドデコレータなどを紹介します。
