【未経験から始めるPython基礎⑨】|クラス変数・インスタンス変数・継承・メソッド・特殊メソッド・dataclassまで

5 min 47 views
オーバーライド

Python のクラスは、最初は難しく感じても、仕組みを順番に学べばとても強力な武器になります。


この記事では、クラス変数/インスタンス変数から始まり、継承、クラスメソッド、静的メソッド、プロパティ、特殊メソッド、そして dataclass まで、実務でも役立つ要素を体系的にまとめました。

1. クラス変数とインスタンス変数の違い

 ✔ クラス変数(class variable)

クラスに属する変数で、全インスタンスで共有される。

class Card:
    all_suit = "♦♥♠♣"   # クラス変数

    def __init__(self, suit, rank):
        self.suit = suit    # インスタンス変数
        self.rank = rank
  • Card.all_suit
  • instance.all_suit → インスタンスからでも参照できる(実際は Card のもの)

定数や共通設定のように「全員が同じ値を使う」ものに向いています。

✔ 特徴

  • クラスに1つだけ存在する
  • すべてのインスタンスから共通で参照できる
  • インスタンス側に同名の変数がなければ自動的にクラス変数が参照される

 ✔ インスタンス変数(instance variable)

各インスタンスが固有に持つデータ。

c1 = Card("♥", 3)
c2 = Card("♣", 10)

print(c1.suit, c2.suit)  # → ♥ ♣(バラバラ)

✔ 特徴

  • 各インスタンスでバラバラの値を持てる
  • __init__ 内で定義されることが多い
  • 他のインスタンスとは共有されない

 クラス変数 vs インスタンス変数の違い

種類どこに属する?共有される?呼び出し方利用例
クラス変数クラスそのものすべてのインスタンスで共有Card.x or instance.xルール、定数、共通設定
インスタンス変数個々のインスタンス共有されないinstance.x個々のデータ(名前、年齢、値など)

パッと見の理解は self が付いてるかどうか が大事です。

2. 継承(Inheritance)|クラスを再利用して拡張する

継承を使うと、既存のクラスを“親クラス(基底クラス)”として受け取り、新しい機能を追加した“子クラス(派生クラス)”を作ることができます。

class Animal:
    def speak(self):
        return "..."

class Dog(Animal):
    def speak(self):
        return "ワン!"   # オーバーライド

 ✔ オーバーライド

子クラスで親クラスのメソッドを上書きすること。

✔ イメージすると…

親から受け継いだルールを、子どもが自分用に少し変えること。

親のまま使ってもいいし、
子どもが「自分はこうしたい!」と上書きしてもOK。

✔ たったこれだけの違い

親クラス(基本の動き)
class Animal:
    def speak(self):
        print("なにか言うよ")
子クラスでオーバーライド(動きを変える)
class Dog(Animal):
    def speak(self):   # ← 同じ名前で書き直している
        print("ワン!")

✔ 実際の動き

a = Animal()
d = Dog()

a.speak()  # → なにか言うよ
d.speak()  # → ワン!

同じ speak() でも、

  • Animal → 親の動き
  • Dog → 子クラスが上書きした動き

となります。

つまりオーバーライドとは?

👉 “親と同じ名前のメソッドを子クラスで作り直すことで、動きを自分仕様に変えること。”

たったこれだけ!
Python の継承の中でも特に使う機会が多い大事なポイントです。

3. super() で親クラスの処理を呼び出す

初期化を拡張したい場合に便利です。

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

class Dog(Animal):
    def __init__(self, name, age):
        super().__init__(name)  # 親クラスの初期化
        self.age = age

4. クラスメソッド(@classmethod)

クラスを第一引数(cls)として扱うメソッド。

  • クラス全体に関わる処理
  • 生成専用のメソッド(ファクトリ)を作りたいときに便利
class User:
    count = 0

    def __init__(self, name):
        self.name = name
        User.count += 1

    @classmethod
    def how_many(cls):
        return cls.count
print(User.how_many())  # → 現在の生成数

5. 静的メソッド(@staticmethod)

selfもclsも使わない、ただの関数をクラスにまとめたいときに使う。

class MathTool:
    @staticmethod
    def add(a, b):
        return a + b
print(MathTool.add(3, 5))  # → 8

用途は「クラスに関連するユーティリティ関数」です。

6. プロパティ(@property)|getter/setterのPythonicな書き方

Python では Java のような getX() setX() を書かず、@property で自然なアクセスを実現できます。

class Person:
    def __init__(self, age):
        self._age = age

    @property
    def age(self):
        return self._age  # 参照

    @age.setter
    def age(self, value):
        if value < 0:
            raise ValueError("年齢は0以上にしてください")
        self._age = value
p = Person(20)
p.age = 30
print(p.age)   # → 30

自然なアクセスなのにバリデーションもできる便利な仕組みです。

7. ダンダーメソッド(特殊メソッド)

Python のオブジェクトをPythonらしく振る舞わせるための“魔法メソッド”。

 代表的なもの

✔ __str__

def __str__(self):
    return f"{self.rank} of {self.suit}"

print(obj) のときに使われる文字列表現。

✔ __repr__(開発者向け)

def __repr__(self):
    return f"Card(suit='{self.suit}', rank={self.rank})"

デバッグ用。再生成可能な表現が理想。

✔ __len__

def __len__(self):
    return len(self.cards)

len(obj) の挙動を定義。

✔ __eq__

def __eq__(self, other):
    return (self.suit, self.rank) == (other.suit, other.rank)

オブジェクトの“同値性”をカスタマイズできます。

8. dataclass|面倒なクラス定義を自動化

Python 3.7+ では @dataclass を使うと、
初期化・比較・repr などの「ボイラープレート(定型コード)」を自動生成できます。

from dataclasses import dataclass

@dataclass
class Card:
    suit: str
    rank: int

この3行だけで自動生成されるもの

  • __init__
  • __repr__
  • __eq__
  • フィールドの保持
    などなど

 使ってみる

c1 = Card("♣", 3)
c2 = Card("♣", 3)

print(c1)        # → Card(suit='♣', rank=3)
print(c1 == c2)  # → True

OOP の基本構造がとてもスッキリします。

9. まとめ|Pythonクラスは“道具箱”のように使い分ける

この記事の内容が理解できれば、Python のオブジェクト指向はほぼ「使える」状態になります。

この記事で紹介した内容をまとめると以下の通りです。

🔹 クラス/インスタンス変数

  • クラス変数は共有データ
  • インスタンス変数は個別データ

🔹 継承とオーバーライド

  • 親の機能を受け継ぐ
  • 子クラスで上書きも可能
  • super() で親の処理を引き継げる

🔹 クラスメソッド & 静的メソッド

  • @classmethod → クラスに関係
  • @staticmethod → self も cls も不要

🔹 プロパティ

  • @property で Pythonic に getter/setter

🔹 ダンダーメソッド

  • __str__ / __repr__ / __eq__ / __len__ などで
    オブジェクトを“Pythonらしく”する

🔹 dataclass

  • 定型コードを自動化
  • 軽いデータ保持クラスを簡単に作れる

関連記事