【Python】レッスン5-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副業)
データクラスとは|initや比較メソッドを自動生成する方法
データクラスを使うと、__init__
・__repr__
・比較メソッドなどを自動生成でき、データを扱うための小さなクラスを最小コードで定義できます。
本記事では、通常のクラス記述との違いに触れつつ、データクラスの基本と使いどころをコンパクトに整理します。
それでは、“書かないコード” で実装を軽くするデータクラスの基礎を、最小サンプルから一緒に押さえていきましょう。
データクラスの基本|@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()
関数や対話型シェルなどでオブジェクトを表示したときに呼び出されます。
詳細は以下のコラムを参照ください。
- コラム:__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
このように、データクラスは現実のアプリケーションにおけるデータ管理を効率化します。
まとめ|書かないコードで小さなデータモデルを素早く
この記事にて、データクラスの基本構文と@dataclass
による自動生成(__init__
、比較メソッド、__repr__
)の仕組みを押さえました。
これにより小さなデータモデルを数行で定義し、読みやすい表示でデバッグし、等価比較や並び替えを安全に扱うことができるようになりました。
冗長なボイラープレートを減らし、“書かないコード” を増やすことで、実装のスピードと品質を両立できるようになります。
学んだ手法を日々のミニプロジェクトや練習問題で繰り返し使い、手に馴染ませていきましょう。
できることが増えるたびに設計の迷いは減り、次の学習にも自然と前向きに取り組めるはずです。
- サイト改善アンケート|ご意見をお聞かせください(1分で終わります)
-
本サイトでは、みなさまの学習をよりサポートできるサービスを目指しております。
そのため、みなさまの「プログラミングを学習する理由」などをアンケート形式でお伺いしています。1分だけ、ご協力いただけますと幸いです。
【Python】サイト改善アンケート
練習問題:データクラスを使ってみよう
この記事で学習した「データクラス」を復習する練習問題に挑戦しましょう。
問題|データクラスで図形の面積と外周を求めよう
円と長方形を表すデータクラスを定義し、面積や外周(円は円周)をインスタンスメソッドで計算して表示するプログラムを作成します。
クラス設計(フィールドとメソッド)、@dataclassによる初期化の自動化、メソッドの戻り値の扱いを一通り確認できる練習です。
以下の要件に従ってコードを完成させてください。
- クラス定義
@dataclass
を用いて、円を表すCircle
と長方形を表すRectangle
を定義する。Circle
はradius: float
のフィールドを持つ。Rectangle
はwidth: float
とheight: float
のフィールドを持つ。
- インスタンスメソッド
- 両クラスに面積を返す
area()
メソッドを実装する。 Circle
に円周を返すcircumference()
メソッドを実装する。Rectangle
に外周を返すperimeter()
メソッドを実装する。- 各メソッドは数値(
float
)を戻り値として返すこと。
- 両クラスに面積を返す
- 利用例の実装
- メインブロックで各クラスのインスタンスをサンプル値で生成する。
- フィールド値と、
area()
/circumference()
/perimeter()
の計算結果を表示する。
ただし、以下のような実行結果となるコードを書くこと。
円の半径: 5 円の面積: 78.54 円周の長さ: 31.42 長方形の幅: 4, 高さ: 7 長方形の面積: 28 長方形の外周: 22
ヒント|難しいと感じる人だけ見よう
1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。
- ヒント1【コードの構成を見る】
-
正解のコードは上から順に以下のような構成となっています。
1:データクラスと数学定数を使うための準備(インポート)
・データクラスのデコレーターは、専用モジュールから個別に読み込む構文を使う。
・円の面積や円周の計算には、円周率などを提供する数学モジュールが必要。
・インポート文はスクリプトの先頭に配置して見通しを良くする。2:円を表すデータクラスと、面積・円周を計算するメソッドの定義
・半径は浮動小数点のフィールドとして1つだけ持たせる。
・面積は「円周率 × 半径の二乗」、円周は「2 × 円周率 × 半径」で求める。
・メソッドはインスタンスの値を使い、数値を戻り値として返す(画面表示は行わない)。3:長方形を表すデータクラスと、面積・外周を計算するメソッドの定義
・フィールドは「横幅」と「高さ」の2つを数値として持たせる。
・面積は「横幅 × 高さ」で求める。
・外周は「2 × (横幅 + 高さ)」で求め、数値を戻り値として返す。4:図形インスタンスを作成し、計算結果を読みやすく表示する
・インスタンス生成はフィールド名と値を対応づける(キーワード引数)。
・面積・円周・外周は各メソッドを呼び出して数値の戻り値を得る。
・表示時はフォーマット指定で小数点以下の桁数や改行を整える。
- ヒント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()}")
このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。
解答例|まるとしかくプログラム
例えば以下のようなプログラムが考えられます。
- 正解コード
-
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()}")
解答例の解説|まるとしかくプログラムの考え方
解答例の詳細解説は以下の通りです。
- 詳細解説
-
インポート文
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()}")
ここでは円と長方形のインスタンスを具体的な数値で作成し、それぞれのメソッドで面積や外周(円は円周)を計算して表示します。
値の受け渡しはフィールド名を指定して行うと、どの数がどの属性に対応しているかが明確になります。
表示にはフォーマット付きの文字列を使い、数値を見やすい桁数に整えたり、適宜改行を入れて出力を区切ることで、結果が一目で理解できる形になります。
計算(メソッドの呼び出し)と表示(文字列の整形)を分けて考えると、処理の流れが整理され、後で表示形式を変更したいときにも対応しやすくなります。
データクラスの疑問解消|FAQと用語のまとめ
初心者がつまずきやすいポイントをFAQとしてまとめ、またよく使う専門用語をわかりやすく整理しました。
理解を深めたいときや、ふと疑問に感じたときに役立ててください。
FAQ|データクラスに関するよくある質問
- Q1. データクラスと通常のクラスの違いは?
-
データクラスは
__init__
や__repr__
などを自動生成するため、定型的なクラス定義が簡潔になります。
- Q2. データクラスは継承できますか?
-
はい、通常のクラスと同様に継承可能です。ただし、自動生成される機能との整合性に注意が必要です。
- Q3. データクラスでフィールドにデフォルト値を設定する方法は?
-
フィールド定義時に
=
でデフォルト値を設定することで、初期値を持つ変数を簡単に定義できます。
Python用語集|データクラスに関する用語一覧
今回の記事で出てきた用語・関数などを一覧で紹介します。
このサイトに出てくる 全てのPython用語をまとめた用語集 も活用してください。
Python用語 | 定義・使い方の概要 | 解説記事へのリンク |
---|---|---|
データクラス | 属性の定義と初期化を簡潔に記述できるクラス。@dataclass デコレーターを使って定義される | 本記事 |
dataclasses モジュール | データクラスをサポートする標準モジュールで、@dataclass やユーティリティ関数を提供 | 本記事 |
__repr__ メソッド | オブジェクトの文字列表現を返す特殊メソッド。デバッグや出力表示用に print() などで利用される | 本記事 |
__eq__ メソッド | 2つのオブジェクトが等しいかを判定する比較演算子 == の動作を定義する特殊メソッド | なし |