【Python】レッスン5-11:データクラスを理解しよう

ながみえ
【Python学習記事のアイキャッチ画像】Lesson5-11 データクラスを理解しよう

一つ前のLessonではミックスインについて学習しました。

今回はデータクラスについて見ていきましょう。

Lesson1:基礎文法編
Lesson2:制御構造編
Lesson3:関数とスコープ編

Lesson4:データ構造編
Lesson5:オブジェクト指向編
・Lesson5-1:クラスの基本を理解しよう
・Lesson5-2:メソッドの基本を理解しよう
・Lesson5-3:カプセル化を理解しよう
・Lesson5-4:プロパティを理解しよう
・Lesson5-5:クラスの継承を理解しよう
・Lesson5-6:メソッドのオーバーライドを理解しよう
・Lesson5-7:静的メソッドを理解しよう
・Lesson5-8:モジュールを使いこなそう
・Lesson5-9:抽象クラスを理解しよう
・Lesson5-10:ミックスインを理解しよう
・Lesson5-11:データクラスを理解しよう ◁今回はココ
・練習問題5-1:モンスター捕獲ゲームを作ろう
・練習問題5-2:モンスターとのバトルゲームを作ろう
次のステップ:Python基礎習得者にお勧めの道5選(実務or副業)

<<前のページ

【Python学習記事のアイキャッチ画像】Lesson5-10 ミックスインを理解しよう

Pythonの記事一覧

Python学習カテゴリの親ページ用アイキャッチ画像(テキスト&問題集)、記事一覧へのリンク案内

次のページ>>

【Python学習記事のアイキャッチ画像】Lesson5-☆1 モンスター捕獲ゲームを作ろう

データクラスとは|initや比較メソッドを自動生成する方法

データクラスを使うと、__init____repr__・比較メソッドなどを自動生成でき、データを扱うための小さなクラスを最小コードで定義できます。

本記事では、通常のクラス記述との違いに触れつつ、データクラスの基本と使いどころをコンパクトに整理します。

それでは、“書かないコード” で実装を軽くするデータクラスの基礎を、最小サンプルから一緒に押さえていきましょう。

【Python】勉強猫がノートパソコンを前にして学習を始める様子。記事内の学習スタート用イラスト

データクラスの基本|@dataclassの書き方と最小サンプル

データクラスはPython 3.7以降で導入された標準ライブラリ dataclassesモジュール が提供する機能です。

データクラスの主な目的は、データを効率的に格納するためのクラスを簡潔に定義することです。

従来の方法では __init__メソッド、__repr__メソッド などを手動で実装する必要がありましたが、データクラスを使うとこれらを自動的に生成できます。

これによりコードが短くなり、可読性が向上します。

まずは、通常のクラス定義の例として、従業員のデータを保持するクラスを見てみましょう。

class Employee:	# クラス定義
    def __init__(self, name: str, age: int, position: str):	# コンストラクタ
        self.name = name
        self.age = age
        self.position = position

この例では、3つのデータ(変数)を持つEmployeeクラスを定義し、__init__メソッド(コンストラクタ)で初期化しています。

これと同じ意味のクラスをデータクラスとして定義することができます。

データクラスを使用するには @dataclassデコレーター を使用します。

from dataclasses import dataclass # dataclassesモジュールのインポート

@dataclass		# データクラスであることを表すデコレーター
class Employee:	# データクラスの定義
    name: str
    age: int
    position: str

データクラスを定義するとり、自動的に以下のようなメソッドが作成されます。

  • __init__: インスタンス生成時の初期化(コンストラクタ)。
  • __repr__: クラスの見やすい文字列表現。
  • __eq__: オブジェクト同士の比較。

例えば、上記のコード内にはコンストラクタは書かれていませんが、インスタンス生成時には使用することができます。

# インスタンス作成。コンストラクタは @dataclass により自動生成される
employee = Employee(name="Alice", age=30, position="Engineer")
# インスタンスの内容を表示。__repr__ メソッドが自動生成されているので整形された文字列が出力される
print(employee)

このコードを実行すると以下のように出力されます。

Employee(name='Alice', age=30, position='Engineer')

なお、データクラスはこのような便利メソッドを自動生成する機能がある以外は、通常のクラスと同じものです。

上記の例ではデータのみを保持していますが、通常のメソッド等を含めることもできます。

__repr__の役割と自動生成|デバッグしやすい表示を手に入れる

Pythonでは、オブジェクトの中身を文字列として表現するために、特殊メソッド __repr__ が使われます。

これは主に開発者向けのデバッグ表示に使用され、print()関数や対話型シェルなどでオブジェクトを表示したときに呼び出されます。

詳細は以下のコラムを参照ください。

Q
コラム:__repr__メソッドとは?

通常のクラスでの __repr__ 定義

通常のクラスでは、__repr__ を自分で定義する必要があります。例えば:

class Product:
    def __init__(self, id, name, price, stock):
        self.id = id
        self.name = name
        self.price = price
        self.stock = stock

    def __repr__(self):
        return f"Product(id={self.id}, name='{self.name}', price={self.price}, stock={self.stock})"

このように、自分でオブジェクトの内容を整形して返す文字列を構築する必要があります。

データクラスでの __repr__ の自動生成

Pythonのデータクラス(@dataclass デコレーターを使ったクラス)では、__repr__ メソッドが自動で生成されます。

開発者は何も書かずとも、オブジェクトの内容をわかりやすく表示できます。

from dataclasses import dataclass

@dataclass
class Product:
    id: int
    name: str
    price: float
    stock: int

product = Product(101, "Laptop", 999.99, 20)
print(product)

このコードでは __repr__ を定義していないにもかかわらず、次のような出力が得られます:

Product(id=101, name=’Laptop’, price=999.99, stock=20)

これは、@dataclass によって自動生成された __repr__ によるものです。

データクラスのメリットと活用例|ボイラープレートを減らす

データクラスを使うことで以下の利点があります。

  • コードの簡潔化:定型的なメソッドの記述を省略できる。
  • 自動生成される機能:比較や文字列表現が簡単。
  • タイプアノテーションのサポート:IDEやエディタでの補完が効率的。

従来のクラスと比較して、データクラスはシンプルなデータ構造を管理するのに最適です。

以下は、商品データを管理する例です。

from dataclasses import dataclass	# dataclassesモジュールのインポート

@dataclass		# データクラスであることを表すデコレーター
class Product:	# データクラスの定義
    id: int
    name: str
    price: float
    stock: int

# インスタンス作成。コンストラクタは @dataclass により自動生成される
product = Product(id=101, name="Laptop", price=999.99, stock=20)

# インスタンスの内容を表示。__repr__ メソッドが自動生成されているので整形された文字列が出力される
print(product)

# 在庫を更新
product.stock -= 1
print(f"Updated stock: {product.stock}") # 更新後の在庫数を表示

このコードではデータクラスを使って商品データを管理しています。

Productクラスは簡潔に商品情報を定義し、__repr__により情報をわかりやすく表示できます。

Product(id=101, name='Laptop', price=999.99, stock=20)
Updated stock: 19

このように、データクラスは現実のアプリケーションにおけるデータ管理を効率化します。

まとめ|書かないコードで小さなデータモデルを素早く

【初心者向け】Pythonのオブジェクト指向を分かりやすくまとめた概念図。 特にクラスの継承、オーバーライド、抽象クラス、ミックスインクラス、データクラス、静的メソッドの関係性を視覚的に理解できるようまとめている。

この記事にて、データクラスの基本構文と@dataclassによる自動生成(__init__、比較メソッド、__repr__)の仕組みを押さえました。

これにより小さなデータモデルを数行で定義し、読みやすい表示でデバッグし、等価比較や並び替えを安全に扱うことができるようになりました。

冗長なボイラープレートを減らし、“書かないコード” を増やすことで、実装のスピードと品質を両立できるようになります。

学んだ手法を日々のミニプロジェクトや練習問題で繰り返し使い、手に馴染ませていきましょう。

できることが増えるたびに設計の迷いは減り、次の学習にも自然と前向きに取り組めるはずです。

Q
サイト改善アンケート|ご意見をお聞かせください(1分で終わります)

本サイトでは、みなさまの学習をよりサポートできるサービスを目指しております。
そのため、みなさまの「プログラミングを学習する理由」などをアンケート形式でお伺いしています。

1分だけ、ご協力いただけますと幸いです。

【Python】サイト改善アンケート
1.このサイトをどのように活用していますか?また、今後どのように活用したいですか?
5.気になっているサービス・商品があれば教えてください。
(複数選択可)
※ 特定の記事に関する内容の場合は、記事番号(Python Lesson〇-〇)をご記入願います。

練習問題:データクラスを使ってみよう

この記事で学習した「データクラス」を復習する練習問題に挑戦しましょう。

【Python】勉強猫がノートパソコンに向かい、練習問題に挑戦する様子。記事内の休憩用イラスト

問題|データクラスで図形の面積と外周を求めよう

円と長方形を表すデータクラスを定義し、面積や外周(円は円周)をインスタンスメソッドで計算して表示するプログラムを作成します。

クラス設計(フィールドとメソッド)、@dataclassによる初期化の自動化、メソッドの戻り値の扱いを一通り確認できる練習です。

以下の要件に従ってコードを完成させてください。

  1. クラス定義
    • @dataclassを用いて、円を表すCircleと長方形を表すRectangleを定義する。
    • Circleradius: floatのフィールドを持つ。
    • Rectanglewidth: floatheight: floatのフィールドを持つ。
  2. インスタンスメソッド
    • 両クラスに面積を返すarea()メソッドを実装する。
    • Circleに円周を返すcircumference()メソッドを実装する。
    • Rectangleに外周を返すperimeter()メソッドを実装する。
    • 各メソッドは数値(float)を戻り値として返すこと。
  3. 利用例の実装
    • メインブロックで各クラスのインスタンスをサンプル値で生成する。
    • フィールド値と、area()circumference()perimeter()の計算結果を表示する。

ただし、以下のような実行結果となるコードを書くこと。

円の半径: 5
円の面積: 78.54
円周の長さ: 31.42

長方形の幅: 4, 高さ: 7
長方形の面積: 28
長方形の外周: 22

ヒント|難しいと感じる人だけ見よう

1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。

Q
ヒント1【コードの構成を見る】

正解のコードは上から順に以下のような構成となっています。

1:データクラスと数学定数を使うための準備(インポート)
 ・データクラスのデコレーターは、専用モジュールから個別に読み込む構文を使う。
 ・円の面積や円周の計算には、円周率などを提供する数学モジュールが必要。
 ・インポート文はスクリプトの先頭に配置して見通しを良くする。

2:円を表すデータクラスと、面積・円周を計算するメソッドの定義
 ・半径は浮動小数点のフィールドとして1つだけ持たせる。
 ・面積は「円周率 × 半径の二乗」、円周は「2 × 円周率 × 半径」で求める。
 ・メソッドはインスタンスの値を使い、数値を戻り値として返す(画面表示は行わない)。

3:長方形を表すデータクラスと、面積・外周を計算するメソッドの定義
 ・フィールドは「横幅」と「高さ」の2つを数値として持たせる。
 ・面積は「横幅 × 高さ」で求める。
 ・外周は「2 × (横幅 + 高さ)」で求め、数値を戻り値として返す。

4:図形インスタンスを作成し、計算結果を読みやすく表示する
 ・インスタンス生成はフィールド名と値を対応づける(キーワード引数)。
 ・面積・円周・外周は各メソッドを呼び出して数値の戻り値を得る。
 ・表示時はフォーマット指定で小数点以下の桁数や改行を整える。

Q
ヒント2【穴埋め問題にする】

以下のコードをコピーし、コメントに従ってコードを完成させて下さい。

from dataclasses import '''(穴埋め)'''
import math

# 円を表すデータクラス
'''(穴埋め)データクラス化するためのデコレーターを書く'''
class Circle:
    radius: '''(穴埋め)'''

    def area(self) -> float:
        # 円の面積を返す
        return math.pi * self.radius ** 2

    def circumference(self) -> float:
        # 円周を返す
        return 2 * math.pi * self.radius


# 長方形を表すデータクラス
'''(穴埋め)データクラス化するためのデコレーターを書く'''
class Rectangle:
    '''(穴埋め)幅と高さのフィールド(width: float, height: float)を型注釈付きで定義'''

    def area(self) -> float:
        # 長方形の面積を返す
        return self.width * self.height

    def perimeter(self) -> float:
        # 長方形の外周を返す
        return 2 * (self.width + self.height)


# --- 利用例 ---
c = Circle('''(穴埋め)'''=5)
print(f"円の半径: {c.radius}")
print(f"円の面積: {c.area():.2f}")
print(f"円周の長さ: {c.circumference():.2f}")

r = Rectangle(width=4, height=7)
print(f"\n長方形の幅: {r.width}, 高さ: {r.height}")
print(f"長方形の面積: {r.area()}")
print(f"長方形の外周: {r.perimeter()}")

このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。

解答例|まるとしかくプログラム

例えば以下のようなプログラムが考えられます。

Q
正解コード
from dataclasses import dataclass
import math

# 円を表すデータクラス
@dataclass
class Circle:
    radius: float

    def area(self) -> float:
        # 円の面積を返す
        return math.pi * self.radius ** 2

    def circumference(self) -> float:
        # 円周を返す
        return 2 * math.pi * self.radius


# 長方形を表すデータクラス
@dataclass
class Rectangle:
    width: float
    height: float

    def area(self) -> float:
        # 長方形の面積を返す
        return self.width * self.height

    def perimeter(self) -> float:
        # 長方形の外周を返す
        return 2 * (self.width + self.height)


# --- 利用例 ---
c = Circle(radius=5)
print(f"円の半径: {c.radius}")
print(f"円の面積: {c.area():.2f}")
print(f"円周の長さ: {c.circumference():.2f}")

r = Rectangle(width=4, height=7)
print(f"\n長方形の幅: {r.width}, 高さ: {r.height}")
print(f"長方形の面積: {r.area()}")
print(f"長方形の外周: {r.perimeter()}")

解答例の解説|まるとしかくプログラムの考え方

解答例の詳細解説は以下の通りです。

Q
詳細解説

インポート文

from dataclasses import dataclass
import math

この部分では、標準ライブラリから必要な機能をあらかじめ読み込む準備をしています。
データクラス用のデコレーターを読み込むことで、クラス定義から初期化や表示用のメソッドを自動で用意できるようになります。
あわせて数学関連のモジュールを読み込むことで、円周率などの定数や数式に役立つ関数を後の計算で使えるようにします。
インポートはプログラムの冒頭にまとめて書くのが基本です。

円を表すデータクラス

# 円を表すデータクラス
@dataclass
class Circle:
    radius: float

    def area(self) -> float:
        # 円の面積を返す
        return math.pi * self.radius ** 2

    def circumference(self) -> float:
        # 円周を返す
        return 2 * math.pi * self.radius

ここでは、円という概念を一つのデータとして扱うための設計を行い、半径をフィールドとして持つクラスを用意します。
データクラスを使うことで、初期化などの定型処理は自動化され、学習者は「何の値を持つか」と「どう計算するか」に集中できます。
計算はインスタンスメソッドとして用意し、保存してある半径を使って面積と円周を求めます。円周率は数学用のモジュールから取得し、計算結果は数値として返します。
各メソッドには短い説明文を添えて、役割がひと目で分かるようにしています。
型ヒントを付けることで、引数や戻り値の想定が明確になり、読みやすさと保守性も高まります。

長方形を表すデータクラス

# 長方形を表すデータクラス
@dataclass
class Rectangle:
    width: float
    height: float

    def area(self) -> float:
        # 長方形の面積を返す
        return self.width * self.height

    def perimeter(self) -> float:
        # 長方形の外周を返す
        return 2 * (self.width + self.height)

ここでは、長方形を一つのデータとして扱うための設計を行い、横幅と高さをフィールドとして持つクラスを用意します。
データクラスを使うことで、値の受け取りや保持といった初期化処理が自動化され、関心を計算ロジックに集中できます。
計算はインスタンスメソッドとして用意し、保存してある横幅と高さを使って面積と外周を求めます。
メソッドは画面表示ではなく数値を返す役割に徹し、短い説明文を添えて役割を明確にします。
型ヒントを付けることで、入力と出力が数値であることが読み取りやすくなり、後からコードを読む人にも意図が伝わりやすくなります。

データクラスの使用

# --- 利用例 ---
c = Circle(radius=5)
print(f"円の半径: {c.radius}")
print(f"円の面積: {c.area():.2f}")
print(f"円周の長さ: {c.circumference():.2f}")

r = Rectangle(width=4, height=7)
print(f"\n長方形の幅: {r.width}, 高さ: {r.height}")
print(f"長方形の面積: {r.area()}")
print(f"長方形の外周: {r.perimeter()}")

ここでは円と長方形のインスタンスを具体的な数値で作成し、それぞれのメソッドで面積や外周(円は円周)を計算して表示します。
値の受け渡しはフィールド名を指定して行うと、どの数がどの属性に対応しているかが明確になります。
表示にはフォーマット付きの文字列を使い、数値を見やすい桁数に整えたり、適宜改行を入れて出力を区切ることで、結果が一目で理解できる形になります。
計算(メソッドの呼び出し)と表示(文字列の整形)を分けて考えると、処理の流れが整理され、後で表示形式を変更したいときにも対応しやすくなります。

もっと分かりやすい学習サイトにするために

この記事を読んで「ここが分かりにくかった」「ここが難しかった」等の意見を募集しています。

世界一わかりやすいPython学習サイトにするため、ぜひ 問い合わせフォーム からご意見下さい。

<<前のページ

【Python学習記事のアイキャッチ画像】Lesson5-10 ミックスインを理解しよう

Pythonの記事一覧

Python学習カテゴリの親ページ用アイキャッチ画像(テキスト&問題集)、記事一覧へのリンク案内

次のページ>>

【Python学習記事のアイキャッチ画像】Lesson5-☆1 モンスター捕獲ゲームを作ろう

データクラスの疑問解消|FAQと用語のまとめ

初心者がつまずきやすいポイントをFAQとしてまとめ、またよく使う専門用語をわかりやすく整理しました。

理解を深めたいときや、ふと疑問に感じたときに役立ててください。

FAQ|データクラスに関するよくある質問

Q
Q1. データクラスと通常のクラスの違いは?

データクラスは__init____repr__などを自動生成するため、定型的なクラス定義が簡潔になります。

Q
Q2. データクラスは継承できますか?

はい、通常のクラスと同様に継承可能です。ただし、自動生成される機能との整合性に注意が必要です。

Q
Q3. データクラスでフィールドにデフォルト値を設定する方法は?

フィールド定義時に=でデフォルト値を設定することで、初期値を持つ変数を簡単に定義できます。

Python用語集|データクラスに関する用語一覧

今回の記事で出てきた用語・関数などを一覧で紹介します。

このサイトに出てくる 全てのPython用語をまとめた用語集 も活用してください。

Python用語定義・使い方の概要解説記事へのリンク
データクラス属性の定義と初期化を簡潔に記述できるクラス。@dataclass デコレーターを使って定義される本記事
dataclasses モジュールデータクラスをサポートする標準モジュールで、@dataclass やユーティリティ関数を提供本記事
__repr__ メソッドオブジェクトの文字列表現を返す特殊メソッド。デバッグや出力表示用に print() などで利用される本記事
__eq__ メソッド2つのオブジェクトが等しいかを判定する比較演算子 == の動作を定義する特殊メソッドなし
記事URLをコピーしました