【Python超入門】「クラスの使い方」と「オブジェクト指向」を初心者向けに解説

Pythonの「class文の使い方」と「オブジェクト指向プログラミング」について入門者向けに解説しています。

オブジェクト指向とは

オブジェクト指向とは、データ(情報)とその操作(ふるまい)をひとまとまりの「オブジェクト」として扱う考え方です。
この考え方に沿ってプログラムを書くことを「オブジェクト指向プログラミング」と呼びます。

基本要素

以下は、オブジェクト指向の基本要素を整理した表です。

項目 説明 RPGの例
オブジェクト データとその操作をひとまとめにしたもの。 「勇者ぴこり」や「魔法使いルーナ」など、ゲーム内のキャラクター。
クラス オブジェクトの設計図。属性やメソッドを定義する。 キャラクターの設計図。「キャラクター」というクラスには、名前・レベル・HPなどの属性と、攻撃・回復などのメソッドが定義されている。
インスタンス クラスから作られた具体的なオブジェクト。 「キャラクター」クラスから「勇者ぴこり」というインスタンス(実際のキャラクター)を作る。
属性 オブジェクトが持つデータ。 名前、レベル、HPなど。
メソッド オブジェクトができる操作(関数)。 攻撃する、防御する、逃げるなど。
カプセル化 属性を外部から直接いじれないようにする仕組み。 キャラクターのHPを勝手に変更できないようにして、メソッド経由でしか操作できないようにする。
継承 既存のクラスを元に新しいクラスを作る仕組み。 「キャラクター」クラスを元に、「村人」クラスなどを作る。
ポリモーフィズム 同じメソッド名でも、クラスごとに動作が変わること。 「attack()」メソッドが、戦士なら剣で攻撃、魔法使いなら魔法で攻撃になる。

イメージ

例えば、「キャラクター設計図」というクラスから、「勇者ぴこり」というインスタンスを生成すると、以下のようになります。

[クラス] キャラクター設計図
 ├─ 属性: 名前, レベル, HP
 └─ メソッド: 攻撃, 防御, 逃げる

↓ クラスからインスタンス(具体的なキャラクター)を生成

[インスタンス] 勇者ぴこり
 ├─ 名前: 兎野ぴこり
 ├─ レベル: 5
 ├─ HP: 120

では、具体的にどのようにPythonでクラスを定義したり、インスタンスを生成するのか次節で解説します。

クラスの定義(class文)とインスタンスの生成

Pythonでは、class文を使ってクラス(設計図)を定義し、そこからインスタンス(実体)を生成します。クラスは「キャラクターの設計図」、インスタンスは「実際に登場するキャラクター」と考えるとわかりやすいです。

書式

# クラスの定義
class クラス名:
    # コンストラクタ(初期化メソッド)
    def __init__(self, 引数1, 引数2):
        self.変数名1 = 引数1
        self.変数名2 = 引数2

    # メソッドの定義
    def メソッド名(self):
        # メソッドの処理内容
        処理

# インスタンスの生成
インスタンス名 = クラス名(値1, 値2)

# インスタンス変数1の値を取得
変数名 = インスタンス名.変数名1

# インスタンス変数の値を書き換え
インスタンス名.変数名2 = 値
項目 内容
class クラス名: クラス定義は class キーワードで始め、クラス名の後にコロン : を付けます。クラス名は 頭文字を大文字にするのが慣習です(例:MyClass)。
def __init__(self, ...) __init__ は「コンストラクタ」と呼ばれ、インスタンス生成時に自動的に呼び出される特別なメソッドです。初期値の設定に使います。
self.変数 = 値 self は「そのインスタンス自身」を指します。インスタンスごとに異なる値を持たせるために使います。
def メソッド名(self): クラス内で定義する関数(=メソッド)は、必ず self を引数に含めます。
インスタンス名 = クラス名(...) クラス名の後に () を付けて呼び出すことで、インスタンス(実体)を生成します。
インスタンス名.変数名 インスタンス変数の値にアクセスします。インスタンス変数とは、そのインスタントが持つ固有の変数のことです。

サンプルコード①

以下は、「キャラクター」クラスを作って、「勇者ぴこり」というインスタンスを生成する例です。

# 「キャラクター」クラスの定義(設計図)
class Character:
    # コンストラクタ(初期化メソッド)
    # キャラクターが誕生するときに呼ばれる特別なメソッド
    def __init__(self, name, level=1, hp=10, mp=0):
        self.name = name    # キャラクターの名前
        self.level = level  # レベル(初期値は1)
        self.hp = hp        # HP(体力)
        self.mp = mp        # MP(魔力)

    # メソッド(攻撃)
    # キャラクターが攻撃魔法を使う動作
    def attack(self):
        print(f"{self.name}は攻撃魔法を唱えた!")

    # メソッド(防御)
    # キャラクターが防御魔法を使う動作
    def guard(self):
        print(f"{self.name}は防御魔法を唱えた!")

    # メソッド(逃げる)
    # キャラクターが戦闘から離脱する動作
    def escape(self):
        print(f"{self.name}は風のように走り去った!")

# 「勇者ぴこり」のインスタンス(実体)を生成
pikori = Character("勇者ぴこり", 5, 120, 10)

# ステータス表示とメソッド呼び出し
print(f"■{pikori.name}のステータス → Lv:{pikori.level}, HP:{pikori.hp}, MP:{pikori.mp}")
pikori.attack()  # 攻撃魔法を使う
pikori.guard()   # 防御魔法を使う
pikori.escape()  # 逃げる

# 「魔法使いルーナ」のインスタンスを生成
luna = Character("魔法使いルーナ", 4, 100, 30)

# ステータス表示とメソッド呼び出し
print(f"\n■{luna.name}のステータス → Lv:{luna.level}, HP:{luna.hp}, MP:{luna.mp}")
luna.attack()  # 攻撃魔法を使う
luna.guard()   # 防御魔法を使う
luna.escape()  # 逃げる

# 「勇者ぴこり」のインスタンス変数(HP、MP)を更新
pikori.hp = 110
pikori.mp = 5

# 「勇者ぴこり」の更新後のステータスを表示
print(f"\n■{pikori.name}の更新後ステータス → Lv:{pikori.level}, HP:{pikori.hp}, MP:{pikori.mp}")
■勇者ぴこりのステータス → Lv:5, HP:120, MP:10
勇者ぴこりは攻撃魔法を唱えた!
勇者ぴこりは防御魔法を唱えた!
勇者ぴこりは風のように走り去った!

■魔法使いルーナのステータス → Lv:4, HP:100, MP:30
魔法使いルーナは攻撃魔法を唱えた!
魔法使いルーナは防御魔法を唱えた!
魔法使いルーナは風のように走り去った!

■勇者ぴこりの更新後ステータス → Lv:5, HP:110, MP:5

サンプルコード②

インスタンス変数はクラス定義の中であらかじめ用意しておくことが多いですが、インスタンス生成後に新しい変数を追加することも可能です。これは「動的な属性追加」と呼ばれ、柔軟な設計ができる反面、管理には注意が必要です。

# 「キャラクター」クラスの定義(設計図)
class Character:
    # コンストラクタ(初期化メソッド)
    # キャラクターが誕生するときに呼ばれる特別なメソッド
    def __init__(self, name, level=1, hp=10, mp=0):
        self.name = name    # キャラクターの名前
        self.level = level  # レベル(初期値は1)
        self.hp = hp        # HP(体力)
        self.mp = mp        # MP(魔力)

    # メソッド(攻撃)
    # キャラクターが攻撃魔法を使う動作
    def attack(self):
        print(f"{self.name}は攻撃魔法を唱えた!")

    # メソッド(防御)
    # キャラクターが防御魔法を使う動作
    def guard(self):
        print(f"{self.name}は防御魔法を唱えた!")

    # メソッド(逃げる)
    # キャラクターが戦闘から離脱する動作
    def escape(self):
        print(f"{self.name}は風のように走り去った!")

# 「勇者ぴこり」のインスタンス(実体)を生成
pikori = Character("勇者ぴこり", 5, 120, 10)

# 「勇者ぴこり」に新しい属性「job(職業)」を追加
pikori.job = "勇者"

# ステータス表示とメソッド呼び出し
print(f"■{pikori.name}のステータス → Lv:{pikori.level}, HP:{pikori.hp}, MP:{pikori.mp}, 職業:{pikori.job}")
■勇者ぴこりのステータス → Lv:5, HP:120, MP:10, 職業:勇者

「pikori」というインスタンス作成後、「pikori.job = “勇者”」書くことで、job という属性が そのインスタンスだけに追加されます。このように、クラス定義には存在しない属性でも、インスタンス単位で持たせることができます。ただし、この方法で追加された属性は、他のインスタンスには存在しません

サンプルコード③

例えば、サンプルコード②の後に、以下のように「魔法使いルーナ」のインスタンスを生成し、 luna.job を表示しようとすると、エラーになります。

# 「魔法使いルーナ」のインスタンスを生成
luna = Character("魔法使いルーナ", 4, 100, 30)

print("「魔法使いルーナ」の職業:{luna.job}")
-Traceback (most recent call last):
File “/tmp/main.py”, line 2, in
import user_code
File “/tmp/user_code.py”, line 38, in
print(f”「魔法使いルーナ」の職業:{luna.job}”)
^^^^^^^^
AttributeError: ‘Character’ object has no attribute ‘job’

このように、インスタンス変数は柔軟に追加できますが、クラス全体で共通の属性にしたい場合は、クラス定義内で明示的に書いておく方が安全です。

クラス変数

Pythonでは、クラス変数は「クラス全体で共通の値」を持つ変数です。 すべてのインスタンス(実体)で共有されるため、個別のキャラクターではなく「世界設定」や「共通ルール」のようなデータを扱うときに使います。

書式

# クラスの定義
class クラス名:
    変数名 = 値  # クラス変数(全インスタンスで共通)


# クラス変数へのアクセス
クラス名.クラス変数名

クラス変数は、クラス文の「直下」に記述します。__init__ の中ではなく、クラスブロックの外側です。

サンプルコード①

class Character:
    # クラス変数(全キャラ共通の設定)
    world_name = "異世界"

    def __init__(self, name):
        self.name = name

# キャラクターを生成
pikori = Character("勇者ぴこり")
luna = Character("魔法使いルーナ")

# クラス変数の参照
print(f"{pikori.name}の世界 → {Character.world_name}")
print(f"{luna.name}の世界 → {luna.world_name}")
勇者ぴこりの世界 → 異世界
魔法使いルーナの世界 → 異世界

このように、クラス変数はインスタンス(キャラ)ごとに違う値を持たず、すべてのインスタンスで共有されます。

サンプルコード②

クラス文で定義されていなくても、あとからクラス変数を追加できます。
以下は、サンプルコード①にクラス変数を追加するコードを追加したものです。

class Character:
    # クラス変数(全キャラ共通の設定)
    world_name = "異世界"

    def __init__(self, name):
        self.name = name

# キャラクターを生成
pikori = Character("勇者ぴこり")
luna = Character("魔法使いルーナ")

# クラス変数の追加
Character.language = "ジャポン語"

# インスタンスからも参照できる
print(f"{pikori.name}の言語 → {pikori.language}")
print(f"{luna.name}の言語 → {luna.language}")
勇者ぴこりの言語 → ジャポン語
魔法使いルーナの言語 → ジャポン語

クラス変数へ代入する際、クラス文で定義されていなかった場合、クラス内に自動的に生成されます。

クラスメソッド

クラスメソッドは、クラス全体に関わる処理を行うメソッドです。クラス名から直接呼び出します。

書式

# クラスの定義
class クラス名:
    # クラスメソッド
    @classmethod
    def メソッド名(cls):

クラスメソッドは、メソッド名の上に @classmethod というデコレータをつけます。
そして、丸括弧内の引数には cls を指定します。これは「クラス自身」を指します(self はインスタンス)。

サンプルコード

クラス継承(スーパークラス・サブクラス)

クラスの継承とは、既に定義しているクラスの機能を流用し、新しいクラスを作成することです。
継承元のクラスを「スーパークラス」、それを用いて新しく作成するクラスを「サブクラス」と言います。
これをうまく使うことでコードの記述量を減らすことが出来ます。

【書式】class サブクラス名(スーパークラス名):

# -*- coding: utf-8 -*-

# スーパークラスの定義
class MyClass1:
    # コンストラクタ(初期化メソッド)
    def __init__(self, x, y):
        self.x = x
        self.y = y


# サブクラスの定義
class SubClass(MyClass1):
    # メソッド(追加分)
    def dot(self):
        self.z = self.x * self.y
        return self.z

# サブクラスのインストラクタを生成
mysub = SubClass(10, 20)

print( mysub.dot() ) # 200
【Python】クラス継承 (スーパークラス・サブクラス)
この記事では、Python言語でクラス継承する方法とソースコードを解説します。

インスタンスを暗黙的に文字列に変換

Pythonでインスタンスを暗黙的に文字列に変換するには、「str()」を用います。

class MyClass:
    def __init__(self, src):
        self.src = src

    def __str__(self):
        return "Hello " + self.src


my = MyClass("Yamada")

print(my) # Hello Takashi

関連ページ(もっと学びたい人へ)

Pythonの基礎から応用例まで、以下ページから学ぶことができます。

【Python超入門】基礎から応用例まで幅広く解説
Pythonの使い方について、基礎文法から応用例まで入門者向けに解説します。
この記事を書いた人
西住技研

プログラミング言語「Python」を研究、仕事、趣味でデータ分析や作業自動化などに活用してきたノウハウを情報発信しています。
筆者の詳しいプロフィールやお問合せはこちらのページまで。
YoutubeX(旧Twitter)でも情報発信中です!

西住技研をフォローする