Python データクラス

PythonBeginner
オンラインで実践に進む

はじめに

この実験 (Lab) では、Python 3.7 以降で利用可能な強力な機能である Python のデータクラス (Dataclasses) について紹介します。データクラスは、主にデータを格納するために使用される通常の Python クラスです。これらはデコレータ @dataclass を使用して、__init__() や __repr__() のような特殊メソッドを自動的に生成するため、ボイラープレートコード (boilerplate code) を大幅に削減できます。

この実験を通して、以下の方法を学びます。

  • 単純なデータクラスの定義方法。
  • 標準的なクラス実装との比較。
  • フィールドのデフォルト値の設定方法。
  • typing.Any の使用を含む型ヒントの扱い方。

この実験の終わりまでに、Python でよりクリーンで簡潔なデータ中心のクラスを作成できるようになるでしょう。

データクラスの機能

このステップでは、データクラスの基本的な機能について学習します。まず、データを格納するための標準的な Python クラスを見てから、データクラスがそれをどのように簡素化するかを確認します。

標準的なクラスでは、属性を初期化するために __init__ メソッドを手動で記述する必要があります。

例えば、数値を表すクラスは次のようになります。

class Number:
    def __init__(self, val):
        self.val = val

obj = Number(2)
print(obj.val)

@dataclass デコレータを使用すると、Python は __init__ メソッドだけでなく、きれいな文字列表現のための __repr__ のような他の便利なメソッドも自動的に生成します。主な要件は、フィールドに型ヒントを提供する必要があることです。

注: WebIDE (VS Code のようなもの) の使用に慣れていない場合は、まずこの実験 (lab)で学習してください。

@dataclass デコレータを使用して、同じ Number クラスを作成してみましょう。

左側のファイルエクスプローラーから features.py ファイルを開きます。以下のコードをファイルに追加してください。

from dataclasses import dataclass

@dataclass  ## このデコレータがクラスをデータクラスに変換します
class Number:
    val: int  ## 型ヒントが必要です

## __init__ メソッドは自動的に作成されます
obj = Number(2)

## 'val' 属性の値を出力します
print(obj.val)

## __repr__ メソッドも自動的に作成され、きれいな表現が得られます
print(obj)

次に、ターミナルからスクリプトを実行して出力を確認します。

python3 features.py

以下の出力が表示されます。最初の行は属性の値であり、2 行目は自動生成された __repr__ メソッドによって提供されるきれいなオブジェクト表現です。

2
Number(val=2)

ご覧のとおり、データクラスのバージョンはより簡潔で、ボイラープレートコードが少なくて済みます。

デフォルト値の使用

このステップでは、データクラスのフィールドにデフォルト値を追加する方法を探ります。これは、一部の属性がオプションである場合に一般的な要件です。

覚えておくべき重要なルールは、デフォルト値を持つフィールドは、デフォルト値を持たないすべてのフィールドの後に宣言されなければならないということです。

name が必須フィールドであり、count と price がオプションでデフォルト値を持つ Product データクラスを作成してみましょう。

ファイルエクスプローラーから defaults.py ファイルを開きます。以下のコードを追加してください。

from dataclasses import dataclass

@dataclass
class Product:
    name: str        ## 必須フィールド
    count: int = 0   ## デフォルト値を持つオプションフィールド
    price: float = 0.0  ## デフォルト値を持つオプションフィールド

## 必須の 'name' フィールドのみを提供してインスタンスを作成
obj = Product("Python")

## 属性を出力して、デフォルト値が機能していることを確認します
print(f"Name: {obj.name}")
print(f"Count: {obj.count}")
print(f"Price: {obj.price}")

次に、ターミナルでスクリプトを実行します。

python3 defaults.py

出力により、count と price が自動的にデフォルト値に割り当てられていることがわかります。

Name: Python
Count: 0
Price: 0.0

この機能により、オプションの属性を持つオブジェクトの作成が非常に便利になります。

型ヒントの処理

このステップでは、データクラスで型ヒントを使用する必要性について理解します。これまでに見てきたように、データクラスを定義する際には、各フィールドに型を指定することが必須です。

しかし、フィールドに対して具体的なデータ型を指定したくない、または指定できない状況が発生する可能性があります。このような場合のために、Python の typing モジュールは Any という特殊な型を提供します。Any を使用すると、値は任意の型であってもよいことを型チェッカーに伝えます。

フィールドに Any を使用するデータクラスを作成してみましょう。

ファイルエクスプローラーから type_hints.py ファイルを開き、以下のコードを追加してください。

from dataclasses import dataclass
from typing import Any

@dataclass
class WithoutExplicitTypes:
   name: Any
   value: Any = 42

## 'name' が文字列であるインスタンスを作成します。'value' はデフォルト値を使用します。
obj1 = WithoutExplicitTypes(name="Test")
print(f"Object 1: name={obj1.name}, value={obj1.value}")

## 'name' が整数で 'value' が文字列である別のインスタンスを作成します。
obj2 = WithoutExplicitTypes(name=123, value="hello")
print(f"Object 2: name={obj2.name}, value={obj2.value}")

次に、ターミナルからスクリプトを実行します。

python3 type_hints.py

以下の出力が表示され、フィールドが異なる型の値を保持できることが示されます。

Object 1: name=Test, value=42
Object 2: name=123, value=hello

Any は柔軟性を提供しますが、コードをより堅牢にし、自己文書化するためには、可能な限り具体的な型を使用することが一般的に良い習慣とされています。

まとめ

この実験(Lab)では、Python のデータクラスを使用して、簡潔で読みやすいデータ中心のクラスを作成する方法を学びました。

以下の主要な概念を扱いました。

  • @dataclass デコレータは、__init__() や __repr__() のような特殊メソッドを自動的に生成し、定型コード(boilerplate code)を削減します。
  • デフォルト値を持つフィールドの定義方法、およびそれらがデフォルト値を持たないフィールドの後に続く必要があるというルール。
  • データクラスにおける型ヒントの必須性、および特定の型を望まないフィールドでの typing.Any の使用方法。

データクラスは、特に主に状態を格納するクラスを扱う際に、クリーンで保守性が高く、効率的なコードを書くためのモダンな Python における強力なツールです。