sec04 - 【初心者向け】Pythonのクラス入門:インスタンス・self・initをわかりやすく解説
スポンサーリンク

クラスとは何か?

Pythonにおける「クラス(class)」とは、オブジェクト(もの)を作るための設計図です。

たとえば、あなたが「車を扱うプログラム」を作りたいとします。1台だけの車であれば、色や速度を固定値で管理しても構いません。しかし、複数の車を同時に扱いたい場合、それぞれの車に色・速度などを個別に持たせたくなります。このときに登場するのが「クラス」です。

クラスを使うことで、車の共通の構造(設計図・クラス)を定義し、そこから複数の実体(インスタンス)を作ることができます。インスタンスは、インスタンス・オブジェクトや、単にオブジェクトと呼ばれることもあります。

クラス定義の最小構成と命名ルール

まずは最も基本的なクラスの定義を見てみましょう。

class Car:
    pass  # まだ中身は空です

解説:

  • class Car::クラスを定義します。
    • class:クラスを定義する時のキーワードです。
    • Car:クラス名です。
      • 命名規則の注意事項は変数と同じですが、Pythonではクラスを定義する時はUpperCamelCase(アッパーキャメルケース)で記述しましょうとされています。アッパーキャメルケースとは、各英単語の先頭を大文字にして繋げて記述する方式で、アンダーバー(_)は使用しません。(参考: Python: pep8, アッパーキャメルケースとは)
    • ::クラスの定義の一番最後に、コロン:が必要です。記述を忘れないようにしましょう。
  • pass:コードとして認識されるが、何も処理を行わないことを明示的に表すキーワードです。まだ具体的な処理を各段階ではないので、passを使用しています。

上記コードを実行しても何も起こりません。今はまだ、何も機能を持たない設計図を定義しただけだからです。

スポンサーリンク

インスタンス化とは?クラスから実体を作る方法

このコードでは、Car というクラスを定義し、そのクラスから my_car というインスタンス(実体)を作っています。

class Car:
    pass  # まだ中身は空です

my_car = Car()
print(my_car)

解説:

  • Car():クラスからインスタンス(実体)を作ります。
  • my_car:生成したオブジェクトを保持する変数です。
  • print(my_car):インスタンスがメモリ上に存在することを確認できます。

出力例:

<__main__.Car object at 0x000001D580F94590>

これは「Carというクラスから作られたオブジェクトが、メモリ上に存在している」ことを意味します。まだ何も機能を持っていませんが、「Carという設計図をもとに、車オブジェクトを1台作った」状態です。

(※アドレス部分は実行環境によって異なります。)

クラスとインスタンスの関係

クラスはあくまで「設計図」であり、それ自体は動作しません。実際に使うには「インスタンス化」して、「具体的なオブジェクト」を生成する必要があります。

クラス名に丸カッコ()を付けることで、Pythonが「インスタンス化」の処理を行います。

Car(クラス) ──▶ Car() ──▶ インスタンス(実際の車)

このように、class で定義した構造をもとに、Car() を実行することで「実際の車」が作られます。

class Car:
    def __init__(self):
        print('車を作成しました!')

car1 = Car()
car2 = Car()
車を作成しました!
車を作成しました!

Car() を呼び出すたびに __init__という特殊なメソッド(後述)が動作して、新しい車(インスタンス)が作られます。同じ設計図からでも、car1car2 はそれぞれ独立した車です。

initメソッドとself: インスタンス変数を使ってオブジェクトにデータを持たせる

__init__メソッドとは、インスタンスが作られるときに自動的に呼ばれる特別なメソッドです。このメソッドの中で「初期化処理(初期設定)」を行います。

メソッドとは

メソッドとは、関数のようなものなのですが、両者の違いは次の通りです。

  • メソッド
    • オブジェクトの「操作」を定義したもののことを指し、インスタンスに紐づいています。
  • 関数
    • 処理をまとめたもので、インスタンスに紐づかずに独立して存在しています。

言葉の定義の違いはあれど、どちらも処理をまとめて定義したものという点においては同じです。厳格に違いを意識しなくてもコードは書けますので、心配しなくて大丈夫です。

selfは、そのインスタンス自身を指すキーワードです。メソッドの最初の引数として必ず指定し、インスタンス変数を操作するときに使います。

次のコードのように、Car('red')として生成された車は「赤色の車」として記録されます。self.colorのように、selfと変数名をドット.で繋げて記述することで、『そのインスタンスに紐づけられた変数var』として管理されます。インスタンス変数は、それぞれのインスタンスが独自の値を保持します。

class Car:
    def __init__(self, color):  # インスタンス作成時に引数として渡された値を受け取る
        self.color = color  # 引数をインスタンス変数に保存

car1 = Car('red')
car2 = Car('blue')

print(car1.color)  # red
print(car2.color)  # blue

コードの解説:

  • __init__
    • インスタンス生成時に自動で呼ばれる初期化メソッドで、1度だけ呼ばれます。
    • Car('red') のようにインスタンスを作るときに値を渡すと、その値は __init__ メソッドで受け取ります。__init__ メソッドの第1引数には、作られたインスタンス自身の情報が自動で渡されるため、通常 self という名前で受け取ります。そのため、インスタンス作成時に渡す値は、第2引数以降として順番に __init__ で受け取ることになります。
  • self
    • そのインスタンス自身を指します。
  • self.color = color
    • 引数で受け取った値をインスタンス変数に代入します。
    • colorの値はメソッドの処理が終了した時に消滅します。(関数と同じ挙動。) インスタンス変数に代入しておくことで、そのインスタンスが破棄されるまで、値を保持し続けることができます。
【処理の流れ】

Car('red') を作る
         │
         ▼
  __init__(self, color)
         │
   self ← my_car  (このインスタンス自身)
   color ← 'red'  (渡した値)
         │
         ▼
  self.color に 'red' をセット

インスタンスメソッドで動作(振る舞い)を定義する

次に「データ(属性)」だけでなく「動作(メソッド)」も持たせてみます。accelerate(加速)という動作を実装します。car.accelerate()のようにメソッドを呼び出すことで、車の加速の処理を行うことができます。

class Car:
    def __init__(self, color):
        self.color = color     # インスタンス変数 color を初期設定
        self.speed = 0         # インスタンス変数 speed(初期値 0)

    def accelerate(self):
        # self.speed を増やす処理
        self.speed += 10
        # f文字列で現在の速度を表示
        print(f'{self.color}の車が加速しました。現在の速度: {self.speed}km/h')

car = Car('red')
car.accelerate()   # インスタンスメソッドの呼び出し
car.accelerate()
print('最終速度:', car.speed)

出力例:

redの車が加速しました。現在の速度: 10km/h
redの車が加速しました。現在の速度: 20km/h
最終速度: 20

上記コードの、重要な処理の解説:

  • self.speed = 0
    • speedをインスタンス変数として初期化(各インスタンスはそれぞれのspeedの値を持つ)。
  • def accelerate(self):
    • accelerateはインスタンスメソッドです。selfによってそのインスタンスの属性へアクセスできます。
  • self.speed += 10
    • 速度を 10 増やします(加速のシンプルなロジック)。
  • car.accelerate()
    • インスタンス.メソッド()のように呼び出します。
    • 呼び出すと self は呼び出されたインスタンス(ここでは car)を参照します。

デフォルト引数で柔軟なクラス初期化を行う

引数にデフォルト値を設定すると、引数を渡さずにインスタンス化できます。

class Car:
    def __init__(self, color='white'):
        self.color = color
        self.speed = 0

car_default = Car()       # color を省略 → デフォルト 'white'
car_green = Car('green')  # color を指定

print(car_default.color)  # 出力: white
print(car_green.color)    # 出力: green

出力例:

white
green

Carクラスをカスタマイズしてみよう

Carクラスをさらにカスタマイズします。加速・減速のメソッドにデフォルト引数を設定したり、現在のステータスを返すメソッドを追加します。

  • model="sedan" のように複数の属性を持たせることで、実際の利用場面を想定した設計になります。
  • status メソッドは辞書を返すようにしてあり、外部で状態を取り扱いやすくしています。
  • acceleratebrake は引数で増減量を指定できるため、柔軟な動作が可能です。
class Car:
    # コンストラクタ (インスタンス生成時に呼ばれる処理の事)
    def __init__(self, color='white', model='sedan'):
        # インスタンス変数: 各インスタンスが個別に持つデータ
        self.color = color      # 車の色
        self.model = model      # 車種
        self.speed = 0          # 現在速度(km/h) - 初期値 0

    # インスタンスメソッド: 加速する
    def accelerate(self, value=10):
        # value 分だけ速度を増やす
        self.speed += value
        print(f'{self.color}の{self.model}が加速しました。現在の速度: {self.speed}km/h')

    # インスタンスメソッド: ブレーキ(減速)
    def brake(self, value=10):
        # 速度は 0 未満にならないように max を使う
        self.speed = max(0, self.speed-value)
        print(f'{self.color}の{self.model}が減速しました。現在の速度: {self.speed}km/h')

    # インスタンスメソッド: 状態表示(returnで情報を返す)
    def status(self):
        return {'color': self.color, 'model': self.model, 'speed': self.speed}

# 使用例
car_a = Car('red', 'coupe')
car_b = Car('blue')  # model はデフォルト 'sedan'

car_a.accelerate(30)
car_a.brake(15)
print('car_a status:', car_a.status())

car_b.accelerate()
print('car_b status:', car_b.status())

出力例:

redのcoupeが加速しました。現在の速度: 30km/h
redのcoupeが減速しました。現在の速度: 15km/h
car_a status: {'color': 'red', 'model': 'coupe', 'speed': 15}
blueのsedanが加速しました。現在の速度: 10km/h
car_b status: {'color': 'blue', 'model': 'sedan', 'speed': 10}

また、ここで重要なのは「同じクラスから作った別々のインスタンスは互いに独立」な点です。car_acar_bでは、車の色・車種・現在速度の値は、それぞれ異なります。

よくある質問Q&A:selfやinitの疑問を解消

Q1. self はキーワードですか?省略してもいいですか?

A1. selfは言語が予約した特別なキーワードではありませんが、慣習として使います。メソッド定義で最初の引数が「そのインスタンス」を受け取ることになっているため、selfを使うのが標準です。別名でも動きますが、他の人が読むと混乱しますので必ず selfを使いましょう。

また、メソッド内で self を指定し忘れる(例:def accelerate(): と書いてしまう)と、インスタンスから呼ぶとエラーになります(TypeError: Car.accelerate() takes 0 positional arguments but 1 was given)。必ずselfを第一引数に書いてください。

Q2. Car() と Car の違いは?

A2. Carは「クラスオブジェクト(設計図)」であり、Car() はそのクラスからインスタンスを生成する呼び出しです。Carに対して () を付けることでインスタンスが作られ、__init__が呼ばれます。

Q3. __init__ を定義しないとどうなる?

A3. __init__を定義しなければ、Python はデフォルトの空の初期化(何もしない)を行います。インスタンスは作れますが、初期化で設定したい属性がある場合は__init__を定義する必要があります。

スポンサーリンク