Python

【Python初心者向け】インスタンスって何?クラス?オブジェクト指向の基礎となるインスタンス化をざっくり解説!

【Python初心者向け】インスタンスって何?クラス?オブジェクト指向の基礎をざっくり解説!

「クラス」「インスタンス」「オブジェクト指向」……Pythonを勉強し始めると、こんなカタカナ用語が一気に押し寄せてきて、「もう無理かも…」ってなること、ありませんか?

大丈夫です!この記事では、そういった概念を できるだけ日常の言葉 に置き換えて、やさしく解説していきます。コードも少しずつステップアップしながら見ていくので、「なんとなくわかった!」から「実際に書ける!」まで連れていきます。


🚀 なぜオブジェクト指向・クラス・インスタンスを学ぶのか

python programming code
python programming code / Photo by Myburgh Roux via Pexels

プログラムが大きくなってくると、変数や関数だけで管理するのがだんだんつらくなります。「どの変数がどの機能に関係してるの?」「同じような処理が何度も出てきて読みにくい…」というカオスな状態になりがちです。

そこで登場するのが オブジェクト指向 という考え方。「関係するデータと処理をひとまとめにして扱おう」という発想です。Webアプリ・ゲーム・業務システムなど、現実世界のほとんどのソフトウェアはこの考え方で作られています。Pythonでもオブジェクト指向は日常的に使われるので、早めに慣れておくと、後々ぐっとコードが書きやすくなりますよ!


📐 クラスとは「設計図」のこと

クラスは 「設計図」 だとイメージしてください。たとえば車の設計図を思い浮かべてみましょう。設計図には「エンジンはここ」「タイヤは4本」「ハンドルはこんな形」といった情報が書かれています。でも設計図そのものは車ではありませんよね。設計図を元に工場で作られて、初めて「実際に乗れる車」ができあがります。

Pythonでも同じです。クラス(設計図) を元に作られた 実体のことインスタンス(またはオブジェクト) と呼びます。そして、クラスから実体を作る操作のことを インスタンス化 といいます。

まずはシンプルな犬クラスで見てみましょう👇

# 【コード例①】クラスの基本構文

class Dog:
    # 犬の設計図を作る
    pass  # まずは中身なしでOK

# インスタンス化: 設計図から実体を作る
pochi = Dog()
shiro = Dog()

print(type(pochi))  # <class '__main__.Dog'>

Dog() と書くだけで、Dogクラスを元にした「ぽち」と「しろ」という2匹の犬オブジェクトが作れました。同じ設計図(クラス)から いくつでも別々の実体(インスタンス) を作れるのがポイントです!


🔧 コンストラクタ __init__ の役割

設計図だけだと「すべての犬が同じ」になってしまいます。実際には「ぽちは柴犬で3歳」「しろはトイプードルで1歳」と、それぞれ違う情報を持たせたいですよね。そこで使うのが __init__(アンダースコア2つ+init+アンダースコア2つ) というメソッドです。

__init__コンストラクタ と呼ばれ、インスタンスを作ったときに 自動的に呼ばれる初期設定の処理 です。「生まれた瞬間に名前と年齢を設定する」イメージです。

# 【コード例②】__init__ でインスタンスに情報を持たせる

class Dog:
    def __init__(self, name, age):
        # インスタンスが作られたとき自動で呼ばれる
        self.name = name  # 名前を設定
        self.age = age    # 年齢を設定

# インスタンス化(引数を渡して初期設定)
pochi = Dog("ぽち", 3)
shiro = Dog("しろ", 1)

print(pochi.name)  # ぽち
print(shiro.age)   # 1

Dog("ぽち", 3) と書くと、裏側で自動的に __init__ が呼ばれて、「name=ぽち、age=3」という情報がそのインスタンスに紐づけられます。


🙋 self って何?初心者がつまずくポイント!

クラスのコードを見ると必ず出てくる self。「なんでいつも第一引数に書くの?」と不思議に思いますよね。

self「このインスタンス自身」 を指しています。たとえば pochi.name の「pochi」の部分が、メソッドの中では self として扱われるイメージです。

少し乱暴に言うと、「自分自身の情報にアクセスするための合言葉」が self です。Pythonでは慣習的に self という名前を使いますが、技術的には別の名前でも動きます(でも self にするのがお約束です)。

# 【コード例③】selfの役割を理解する

class Dog:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def bark(self):
        # self.name で「自分自身の名前」を参照できる
        print(f"{self.name}:わんわん!")

    def introduce(self):
        print(f"私は{self.name}、{self.age}歳です!")

pochi = Dog("ぽち", 3)
shiro = Dog("しろ", 1)

pochi.bark()       # ぽち:わんわん!
shiro.introduce()  # 私はしろ、1歳です!

pochi.bark() と呼ぶと、Pythonは自動的に self の部分に pochi を渡してくれます。だから self.name が「ぽち」になるんですね。


⚙️ メソッドとプロパティの違い

クラスの中には メソッドプロパティ という2種類の要素があります。

  • プロパティ(属性):インスタンスが持つ「データ・情報」のこと。例えば self.nameself.age がこれにあたります。名詞的なイメージです。
  • メソッド:インスタンスができる「動作・処理」のこと。例えば bark()introduce() がこれにあたります。動詞的なイメージです。

犬で例えると、「名前・年齢・毛色」はプロパティ(情報)、「吠える・走る・お手をする」はメソッド(動作)というイメージです。


🚗 複数のインスタンスを作ってみよう

同じクラスから複数のインスタンスを作っても、それぞれのデータは独立しています。車クラスで確認してみましょう。

# 【コード例④】同じクラスから複数のインスタンスを作る

class Car:
    def __init__(self, maker, color, speed=0):
        self.maker = maker    # メーカー名
        self.color = color    # 車の色
        self.speed = speed    # 現在のスピード(初期値は0)

    def accelerate(self, amount):
        # アクセルを踏む
        self.speed += amount
        print(f"{self.maker}が加速!現在 {self.speed} km/h")

    def brake(self):
        # ブレーキをかける
        self.speed = 0
        print(f"{self.maker}が停車しました")

# 2台の車を作る(同じ設計図から別々の実体)
fj_cruiser = Car("トヨタ", "白")
prius = Car("トヨタ", "赤")

fj_cruiser.accelerate(60)  # トヨタが加速!現在 60 km/h
prius.accelerate(40)       # トヨタが加速!現在 40 km/h

# それぞれのスピードは独立している
print(fj_cruiser.speed)  # 60
print(prius.speed)       # 40

fj_cruiser.brake()  # トヨタが停車しました
print(fj_cruiser.speed)  # 0(priusのスピードには影響しない)
print(prius.speed)       # 40(こちらは変わらず)

fj_cruiser のスピードを変えても、prius のスピードは変わらない。これが「それぞれのインスタンスがデータを独立して持つ」ということです!


🛒 実践例:Flaskショッピングカートをクラスで作る

最後に、より実践的な例を見てみましょう。Webショッピングサイトの「カート機能」をクラスで表現したコードです。「商品を追加する」「商品を削除する」「カートの中身を確認する」という動作を、一つのクラスにまとめています。

# 【コード例⑤】ショッピングカートをクラスで実装

class Cart:
    def __init__(self):
        # カートを作成したとき、中身は空リストで初期化
        self._items = []

    @property
    def items(self):
        # カートの中身を返す(読み取り専用プロパティ)
        return self._items

    def add_item(self, item_name, price, quantity=1):
        """カートに商品を追加する"""
        # 同じ商品が既にあれば数量を増やす
        for item in self._items:
            if item["name"] == item_name:
                item["quantity"] += quantity
                print(f"「{item_name}」の数量を増やしました(合計 {item['quantity']} 個)")
                return

        # 新しい商品を追加
        self._items.append({
            "name": item_name,
            "price": price,
            "quantity": quantity
        })
        print(f"「{item_name}」をカートに追加しました")

    def remove_item(self, item_name):
        """カートから商品を削除する"""
        self._items = [item for item in self._items if item["name"] != item_name]
        print(f"「{item_name}」をカートから削除しました")

    def total_price(self):
        """合計金額を計算して返す"""
        return sum(item["price"] * item["quantity"] for item in self._items)

    def show(self):
        """カートの中身を表示する"""
        print("--- カートの中身 ---")
        if not self._items:
            print("カートは空です")
            return
        for item in self._items:
            print(f"  {item['name']}:{item['price']}円 × {item['quantity']}個")
        print(f"合計:{self.total_price()}円")
        print("-------------------")


# --- 実際に使ってみる ---

# ユーザーAのカートを作成(インスタンス化)
user_a_cart = Cart()

user_a_cart.add_item("Pythonの教科書", 2800)
user_a_cart.add_item("メカニカルキーボード", 12000)
user_a_cart.add_item("Pythonの教科書", 2800)  # 同じ商品を追加
user_a_cart.show()

user_a_cart.remove_item("メカニカルキーボード")
user_a_cart.show()

# ユーザーBのカートは完全に別物
user_b_cart = Cart()
user_b_cart.add_item("USBハブ", 3500, quantity=2)
user_b_cart.show()

実行すると次のように動きます:

# 出力結果
「Pythonの教科書」をカートに追加しました
「メカニカルキーボード」をカートに追加しました
「Pythonの教科書」の数量を増やしました(合計 2 個)
--- カートの中身 ---
  Pythonの教科書:2800円 × 2個
  メカニカルキーボード:12000円 × 1個
合計:17600円
-------------------
「メカニカルキーボード」をカートから削除しました
--- カートの中身 ---
  Pythonの教科書:2800円 × 2個
合計:5600円
-------------------
「USBハブ」をカートに追加しました
--- カートの中身 ---
  USBハブ:3500円 × 2個
合計:7000円
-------------------

user_a_cartuser_b_cart は同じ Cart クラスから作られていますが、それぞれ別々のカートとして独立して動いています。これがクラスとインスタンスの強みです!


📊 まとめ:クラス・インスタンス・オブジェクトの関係

最後に、今回学んだ内容をテキスト図で整理しておきましょう。

【クラス・インスタンス・オブジェクトの関係図】

  ┌─────────────────────────────────────┐
  │         Car クラス(設計図)         │
  │  プロパティ: maker, color, speed     │
  │  メソッド  : accelerate(), brake()  │
  └──────────────┬──────────────────────┘
                 │ インスタンス化(設計図から実体を作る)
        ┌────────┴────────┐
        ↓                ↓
  ┌───────────┐    ┌───────────┐
  │ fj_cruiser │    │   prius   │
  │ maker:トヨタ│    │ maker:トヨタ│
  │ color: 白  │    │ color: 赤  │
  │ speed: 60  │    │ speed: 40  │
  └───────────┘    └───────────┘
  (インスタンス①)  (インスタンス②)

  ✅ クラス    = 設計図(ひとつ)
  ✅ インスタンス = 設計図から作った実体(いくつでも作れる)
  ✅ オブジェクト = インスタンスとほぼ同じ意味で使われる言葉
  ✅ self      = 「このインスタンス自身」を指す

今回のポイントをおさらいすると:

  • 🏗️ クラス:データと処理をひとまとめにした「設計図」
  • 🚗 インスタンス化:クラスを元に実体(オブジェクト)を作ること
  • 🔧 __init__:インスタンス作成時に自動で呼ばれる初期設定メソッド
  • 🙋 self:「このインスタンス自身」を指す特別な引数
  • 📦 プロパティ:インスタンスが持つデータ(名詞)
  • メソッド:インスタンスができる動作(動詞)

最初はとっつきにくく感じるオブジェクト指向ですが、「設計図から実体を作る」というイメージを軸に考えれば、だんだん直感的に理解できるようになります。まずは今回のコード例をそのままコピーして、自分で動かしてみること が一番の近道です。ぜひ試してみてください!💪

📚 関連商品・おすすめ書籍

スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)

もしも

スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)

初心者に定番のPython入門書

Amazonで見る
実践Claude Code入門―現場で活用するためのAIコーディングの思考法

もしも

実践Claude Code入門―現場で活用するためのAIコーディングの思考法

AIコーディングの現場活用法を学ぶ一冊

Amazonで見る
Python Web開発実践入門 ―― FastAPIによるWebAPI開発と非同期処理

もしも

Python Web開発実践入門 ―― FastAPIによるWebAPI開発と非同期処理

FastAPIでWebAPI開発を実践的に学ぶ

Amazonで見る

※本記事にはアフィリエイトリンクが含まれます。

ABOUT ME
やまちゃん
これまで学生と社会人を合わせて5000人以上にプログラミング学習を指導。 ゼロからイチをわかりやすく解説する専門家として活動しており、本業ではArduinoを用いたIoT開発とロボットプログラミングが専門。 Pythonを用いたアプリ開発、ウェブアプリケーションの開発で業務の効率化をサポートしています。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です