クラスとインスタンスについて説明します。クラスとは本来「同じ種類の集まりとして分類する」という意味です。学校のクラスも同じような年齢の生徒を分類したいものと考えることができます。しかし学校のクラスというイメージはまずは捨て去った方がいいです。
pythonでのクラスは属性や動作の定義された設計図にたとえられます。
これに対してインスタンスは「具体的なもの」、「実体」という意味で、クラスを使って、具体的なもの(オブジェクト)を作ったのがインスタンスです。
チョコレートケーキのレシピがクラス、実際にできたチョコレートケーキがインスタンスと考えればよいでしょう。
「クラスの定義はやや複雑に見えますが、インスタンスの生成は比較的シンプルです。
インスタンス名=クラス名(引数1、引数2)
で表されます。チョコレートケーキの例でいえば、引数はスポンジの種類や飾りつけの種類ということになります。

なぜクラスとインスタンスが重要か
クラスとインスタンスは、オブジェクト指向プログラミング(OOP)の重要な要素です。オブジェクトとは、データ(属性)とそれに関連する処理(メソッド)をひとまとめにしたものです。たとえば、ゲームでは「キャラクター」「敵」「アイテム」などをオブジェクトとして定義できます。現実世界の構造を反映しやすく、直感的に設計しやすいのが特徴です。クラスでは共通する性質や動作をひとまとめにできるため、同じ処理を何度も書く必要がなく、コードの再利用が容易になります。さらに、修正や機能追加がしやすく、他の部分に影響を与えにくいため、保守も簡単です。大規模開発やチーム作業にも適しており、効率的なプログラミングが可能になります。
実際のプログラム
クラスのプログラムを書いてみましょう。属性(データ)は、__init__で表し、動作(メソッド)は名前を付けて定義します。自分自身という意味でselfを使います。
class クラス名:
def __init__(self, 属性1, 属性2, ...):
self.属性1 = 属性1
self.属性2 = 属性2
def メソッド名(self):
処理
チョコレートケーキというクラスで、属性を種類と名前とし、動作を「食べた。おいしい!」と出力する場合は以下になります。
class ChocolateCake:
def __init__(self, kind, name):
self.kind = kind # 属性:種類(ビター/ミルクなど)
self.name = name # 属性:ケーキの名前
def eat(self):
print(f"{self.name}({self.kind}チョコ)を食べた。おいしい!")
これに実際のチョコレートの情報を入れれば、物体として動きます。「ビターチョコ(ガトーショコラ)を食べた。おいしい!」といった動きです。
インスタンスは、
インスタンス名=クラス名(属性1、属性2)
という形で指定します。属性の内容は
print(インスタンス名.属性1)
などとします。動作は
インスタンス名.動作名()
です。
ガトーショコラとオペラについてインスタンスを作ると以下のようになります。
gateau = ChocolateCake("ビター", "ガトーショコラ")
opera = ChocolateCake("コーヒー風味", "オペラ")
print(gateau.name)
print(opera.kind)
gateau.eat()
opera.eat()
出力は、以下になります。
ガトーショコラ
コーヒー風味
ガトーショコラ(ビターチョコ)を食べた。おいしい!
オペラ(コーヒー風味チョコ)を食べた。おいしい!
クラスのわかりにくさはなぜ?
クラスは、「どんな属性があり、どんな動作をするか」を定義する設計図のようなものです。たとえば次のように書けそうに思えます:
class クラス名
def 属性名1
属性1
def 属性名2
属性2
def メソッド名
処理
一見すると、これで属性やメソッドを定義しているように見えます。しかし実際には、この書き方では設計図ではなく、すでに作られた具体的なオブジェクト(インスタンス)を表すような構造になってしまいます。
なぜなら、このような書き方では属性1や属性2の「値」もすでに決まってしまっていて、すべてのオブジェクトが同じ内容になってしまうからです。
オブジェクトごとに異なる値(例:ケーキの名前や味など)を持たせたい場合は、インスタンスを作るときに属性を設定できるようにしなければなりません。そのために使われるのが、Pythonの特別なメソッド __init__
と、インスタンス自身を表すキーワード self
です。
class クラス名:
def __init__(self, 属性1, 属性2, ...):
self.属性1 = 属性1
self.属性2 = 属性2
def メソッド名(self):
処理
このように書くことで、インスタンスを作るときにそれぞれの値を受け取り、オブジェクトごとに違うデータを持たせることができるようになります。
