Pythonのインスタンス変数とクラス変数の違い!selfの使い方を初心者向けに解説
生徒
「Pythonのクラスの中でselfをよく見かけるんですが、これって何ですか?インスタンス変数ってやつですか?」
先生
「selfはそのクラスから作られた“自分自身”のことを指すんだ。そして、インスタンス変数やクラス変数と一緒に使うことが多いんだよ。」
生徒
「えっ?クラス変数って何ですか?インスタンス変数とどう違うんですか?」
先生
「それはとても大事なポイントだね。じゃあ、インスタンス変数とクラス変数の違いと、selfの使い方をじっくり解説していこう!」
1. Pythonのインスタンス変数とは?自分専用のデータを保持する仕組み
Python(パイソン)のインスタンス変数とは、一言で言うと「作成されたオブジェクト(インスタンス)ごとに独立して保持される専用の変数」のことです。
オブジェクト指向プログラミングでは、クラスを「設計図」、インスタンスを「設計図から実体化した製品」に例えます。インスタンス変数は、その製品一つひとつに貼られた「固有のラベル」のような役割を果たします。同じ設計図から作られても、製品ごとにシリアル番号や色が違うように、インスタンス変数も個別に異なる値を持つことができるのです。
インスタンス変数を定義する際は、必ず self.変数名 という形式を使います。この self は「そのインスタンス自身」を指しており、これがあることで「これは私だけのデータだよ」とコンピュータに教えることができます。
class Car:
def __init__(self, color, owner):
# selfをつけることで、インスタンス変数として登録される
self.color = color # インスタンス変数(車の色)
self.owner = owner # インスタンス変数(持ち主)
# 同じCarクラスから、別々のデータを持つインスタンスを作成
car1 = Car("赤", "田中さん")
car2 = Car("青", "佐藤さん")
print(f"{car1.owner}の車の色は{car1.color}です。")
print(f"{car2.owner}の車の色は{car2.color}です。")
上記のコードでは、car1 と car2 という2つのインスタンスが作られています。self.color という名前は共通ですが、中身は「赤」と「青」というように、それぞれが独立した情報として保存されているのが分かりますね。
このように、個別の状態(プロパティ)を管理したい場合には、インスタンス変数の利用が不可欠となります。
2. クラス変数とは?インスタンス変数との違いをわかりやすく解説
Pythonのオブジェクト指向を学ぶ上で、避けて通れないのが「クラス変数」です。前項で触れたインスタンス変数が「個別のデータ」を扱うのに対し、クラス変数は「そのクラスから作られるすべてのインスタンスで共有されるデータ」を管理するために使います。
例えば、ゲームのキャラクターを作るとき、「名前」や「体力」は個別に違いますが、「重力の設定」や「種族名」など、全員に共通するルールはクラス変数で定義するのが効率的です。これにより、メモリの節約やコードの管理が格段に楽になります。
クラス変数は、クラスの直下(メソッドの外側)で定義します。
class Animal:
# クラス変数:すべての動物で共通
species = "動物"
def __init__(self, name):
# インスタンス変数:それぞれの名前は違う
self.name = name
# 2つのインスタンスを作成
dog = Animal("ポチ")
cat = Animal("タマ")
# クラス変数はどちらからアクセスしても同じ値
print(f"{dog.name}は{dog.species}です。")
print(f"{cat.name}は{cat.species}です。")
上記のサンプルプログラムでは、speciesという変数がクラス変数です。dog(ポチ)もcat(タマ)も、同じAnimalクラスから生まれた仲間なので、共通して「動物」というデータを持っています。もし途中でクラス変数の値を書き換えれば、すべてのインスタンスにその変更が反映されるという特徴があります。
このように、「個別の情報(インスタンス変数)」と「共通のルール(クラス変数)」を使い分けることが、スッキリとしたPythonプログラムを書くための第一歩です。
3. 実際にインスタンス変数とクラス変数を使ってみよう
Pythonのオブジェクト指向を理解する最大の近道は、実際にコードを動かして「データの持ち方」の違いを体感することです。ここでは、プログラミングが初めての方でも直感的にイメージしやすいよう、動物を例にしたシンプルなサンプルプログラムで解説します。
「個別の名前(インスタンス変数)」と「共通の種類(クラス変数)」が、メモリ上でどのように扱われているかに注目してみましょう。
class Animal:
# すべての個体に共通するデータ(クラス変数)
species = "動物"
def __init__(self, name):
# その個体だけのデータ(インスタンス変数)
self.name = name
# 2つの「実体(インスタンス)」を作ります
a1 = Animal("ライオン")
a2 = Animal("ゾウ")
# それぞれの名前(インスタンス変数)を表示
print(f"個体1の名前: {a1.name}")
print(f"個体2の名前: {a2.name}")
# 共通の種族(クラス変数)を表示
print(f"個体1の種族: {a1.species}")
print(f"個体2の種族: {a2.species}")
個体1の名前: ライオン
個体2の名前: ゾウ
個体1の種族: 動物
個体2の種族: 動物
実行結果を見ると、a1とa2はそれぞれ「ライオン」「ゾウ」という異なるインスタンス変数を持っています。これは、個体ごとに独立した情報が保存されているためです。
一方で、speciesというクラス変数は、どちらのインスタンスからアクセスしても同じ「動物」という値を参照しています。クラス変数は、そのクラスから生まれたすべてのインスタンスで共有される「共通の看板」のような役割を果たしているのがわかりますね。
このように、データが「個別のもの」か「共通のもの」かを使い分けることで、効率的で整理されたコードを書くことができるようになります。
4. クラス変数は「全体共通」、インスタンス変数は「個別の情報」
オブジェクト指向の中で最も混同しやすいのが、この2つの変数の使い分けです。初心者の方は、インスタンス変数は「個人の持ち物(スマホなど)」、クラス変数は「クラス全員で使う備品(教室の時計など)」とイメージすると、その違いがスッと理解できます。
インスタンス変数
生成された「モノ」ごとに独立した値を持ちます。名前、年齢、身長など、個体差があるデータに使います。
クラス変数
そのクラスから作られた全てのインスタンスで「共有」される値です。組織名や消費税率など、全体で統一すべきデータに使います。
具体的なPythonのコードで、その挙動の違いを確認してみましょう。クラス変数を書き換えると、全てのデータに影響が及ぶ様子がわかります。
class Student:
# クラス変数(全員共通の学校名)
school_name = "Tech学園"
def __init__(self, name):
# インスタンス変数(ひとりひとりの名前)
self.name = name
# インスタンスを作成
s1 = Student("田中")
s2 = Student("佐藤")
print(f"{s1.name}さんの学校: {s1.school_name}") # 田中さんの学校: Tech学園
print(f"{s2.name}さんの学校: {s2.school_name}") # 佐藤さんの学校: Tech学園
# クラス変数を変更すると、全員分が一度に変わる!
Student.school_name = "プログラミング大学"
print(f"{s1.name}さんの学校: {s1.school_name}") # 田中さんの学校: プログラミング大学
print(f"{s2.name}さんの学校: {s2.school_name}") # 佐藤さんの学校: プログラミング大学
注意ポイント: クラス変数は「1箇所変えるだけで全員に反映される」という強力なメリットがありますが、意図せず値を書き換えてしまうと、プログラム全体で予期せぬ不具合(バグ)を招く原因にもなります。基本的には「個別のデータはインスタンス変数」に持たせるのが設計のセオリーです。
5. クラス変数を書き換えるとどうなる?(注意点と挙動)
Pythonのクラス変数を扱う際に、初心者が最も陥りやすい「落とし穴」があります。それは、インスタンス経由で値を書き換えても、元のクラス変数は変わらないという点です。
実は、インスタンスに対してクラス変数と同じ名前で代入を行うと、そのインスタンス専用の「インスタンス変数」が新たに生成されてしまいます。これにより、共有データだったはずが、特定の個体だけの個別データに切り替わってしまうのです。
class Animal:
species = "動物" # これがクラス変数(みんなで共有)
def __init__(self, name):
self.name = name
# 2つのインスタンスを作成
a1 = Animal("キリン")
a2 = Animal("サイ")
# a1の「species」だけを書き換えてみる
a1.species = "哺乳類"
print(f"{a1.name}の種類: {a1.species}")
print(f"{a2.name}の種類: {a2.species}")
print(f"元のクラスの共通設定: {Animal.species}")
キリンの種類: 哺乳類
サイの種類: 動物
元のクラスの共通設定: 動物
実行結果を見ると分かる通り、a1.species を書き換えても a2 や元の Animal クラスには全く影響していません。これは a1 という箱の中に、新しく species という名前のラベル(インスタンス変数)が貼られただけだからです。
このように、意図せず「共有設定」を壊して「個別設定」にしてしまうミスは、プログラミング初心者によく見られます。もし全ての個体で共有している値を一斉に変えたい場合は、インスタンス名ではなく Animal.species = "..." のようにクラス名を使って直接操作する必要があります。
6. selfの意味と役割を理解しよう
selfはPythonのクラスの中で「自分自身のこと」を指すキーワードです。
たとえばself.nameと書くと、「そのオブジェクト自身のname変数」を意味します。selfを使わずに変数を書いてしまうと、ローカル変数(関数の中だけで使われる変数)になってしまいます。
class Student:
def __init__(self, name):
name = name # これは間違い
s = Student("たかし")
print(s.name) # エラーになる
このように、selfをつけないと、クラスの外から使うことができません。正しくは以下のように書きます。
class Student:
def __init__(self, name):
self.name = name # 正しい
7. 実生活にたとえてもう一度整理しよう
Pythonのクラスを「学校のクラス」にたとえてみましょう。
- クラス変数:「みんなが3年1組である」という共通情報
- インスタンス変数:「名前・出席番号・性別」など一人ひとりの情報
- self:「私自身(たろうくん自身・はなこさん自身)」を表す
このようにイメージすると、変数の役割やselfの意味が自然と理解できるようになります。