2026-08-04

【備忘録】Python の @dataclass

Python の @dataclass は、データを保持するクラスを簡潔に記述するためのデコレータです [1]。通常であれば自分で実装する必要がある __init__()__repr__()__eq__() などの定型コードを自動生成してくれるため、コード量を大幅に減らすことができます。

@dataclass デコレータの利用例

通常のクラスであれば、次のようにコンストラクタを実装する必要があります。

class Config:
    def __init__(self):
        self.host = "localhost"
        self.port = 8080
        self.timeout = 30

一方、@dataclass を利用すると、次のようにメンバー変数(ここでは「フィールド」と呼びます)を宣言するだけで同じようなクラスを作成できます。

from dataclasses import dataclass

@dataclass
class Config:
    host: str = "localhost"
    port: int = 8080
    timeout: int = 30

@dataclass は、フィールドの宣言から __init__() を自動生成してくれるため、自分でコンストラクタを書く必要がありません。また、オブジェクトの内容を分かりやすく表示する __repr__() や、オブジェクト同士を比較する __eq__() なども自動的に用意されます。

このサンプルでは 3 つのフィールドだけなので、ありがたみが分かりにくいのですが、何十ものフィールドを扱うときには管理が楽なので、@dataclass デコレータを利用しています。

データクラス という名前から、メソッドを持たない単純なクラスを想像しがちですが、実際には通常のクラスとほぼ同じようにメソッドを追加できます。そのため、データだけでなく、そのデータに関連する処理も自然に記述できます。

今回は、@dataclass を利用する際によく悩む「他のクラスのインスタンスをどこで生成するか」について、__post_init__() を使った方法を備忘録としてまとめました。

他のインスタンスを初期化する方法

@dataclass デコレータを付けたクラスでは、__init__() が自動生成されるため、他のクラスのインスタンスを生成したい場合には __post_init__() を利用します。

from dataclasses import dataclass, field

class Processor:
    def __init__(self, size: int):
        self.size = size

@dataclass
class Config:
    buffer_size: int = 1024

    processor: Processor = field(init=False)

    def __post_init__(self):
        self.processor = Processor(size=self.buffer_size)

ポイント

  • field(init=False) を指定すると、そのフィールドは @dataclass が生成する __init__() の引数に含まれません。
  • __post_init__()@dataclass が生成した __init__() の直後に呼び出されます。
  • そのため、この例のように buffer_size の値を引数にして Processor のインスタンスを生成することができます。

このパターンを覚えておくと、@dataclass を利用しながら、通常のクラスと同じように他のオブジェクトを保持・初期化できるようになります。

参考サイト

  1. dataclasses --- データクラス — Python ドキュメント

 

ブログランキング・にほんブログ村へ bitWalk's - にほんブログ村 にほんブログ村 IT技術ブログ オープンソースへ
にほんブログ村

オープンソース - ブログ村ハッシュタグ
#オープンソース



このエントリーをはてなブックマークに追加