<一覧に戻る

クラス変数

オブジェクト指向プログラミング(OOP)におけるクラス変数は、クラス全体で共有される変数であり、クラスのすべてのインスタンス間で共通のデータを保持します。クラス変数は、インスタンスごとに異なる属性(インスタンス変数)とは対照的に、クラスレベルで一度定義されるため、すべてのインスタンスからアクセスおよび変更が可能です。このセクションでは、Pythonを用いてクラス変数の基本的な概念と実装方法を初心者にもわかりやすく解説します。

クラス変数とは?

クラス変数は、クラス自体に属する変数であり、クラスのすべてのインスタンスで共有されます。クラス変数は、インスタンス間で共通のデータを保持するために使用されます。これにより、例えば、クラスの総インスタンス数や共通の設定値などを管理することができます。

インスタンス変数との違い

  • インスタンス変数:
  • 各インスタンス固有のデータを保持します。
  • インスタンスごとに異なる値を持つことができます。

  • クラス変数:

  • クラス全体で共有されるデータを保持します。
  • すべてのインスタンスで同じ値を持ちます。

クラス変数の定義方法

クラス変数は、クラスの内部でメソッドの外側に定義します。以下に、クラス変数とインスタンス変数の定義方法を示します。

サンプルコード

class Dog:
    # クラス変数
    species = "Canis familiaris"

    def __init__(self, name, age):
        # インスタンス変数
        self.name = name
        self.age = age

    def bark(self):
        return f"{self.name} says woof!"

説明

  • クラス変数 species:
  • クラス全体で共有される属性です。
  • すべての Dog インスタンスで同じ値を持ちます。

  • インスタンス変数 nameage:

  • 各インスタンス固有のデータを保持します。
  • インスタンスごとに異なる値を持つことができます。

クラス変数へのアクセス方法

クラス変数は、クラス名を通じて直接アクセスすることも、インスタンスを通じてアクセスすることもできます。ただし、インスタンスを通じてアクセスした場合でも、クラス変数はすべてのインスタンスで共有されます。

サンプルコード

# Dogクラスのインスタンスを生成
dog1 = Dog("Buddy", 3)
dog2 = Dog("Lucy", 5)

# クラス変数にアクセス(クラス名を使用)
print(Dog.species)  # 出力: Canis familiaris

# クラス変数にアクセス(インスタンスを使用)
print(dog1.species)  # 出力: Canis familiaris
print(dog2.species)  # 出力: Canis familiaris

# クラス変数の変更(クラス名を使用)
Dog.species = "Canis lupus familiaris"

print(dog1.species)  # 出力: Canis lupus familiaris
print(dog2.species)  # 出力: Canis lupus familiaris

説明

  • クラス変数 species は、クラス名 Dog を通じて直接アクセスできます。
  • インスタンス dog1dog2 を通じてもアクセスできますが、どちらも同じクラス変数を参照しています。
  • クラス変数をクラス名を使って変更すると、すべてのインスタンスでその変更が反映されます。

クラス変数の実践例

クラス変数を使用して、クラス全体で共有される情報を管理する例を見てみましょう。例えば、Dog クラスのインスタンス数を追跡する場合です。

サンプルコード

class Dog:
    # クラス変数
    species = "Canis familiaris"
    number_of_dogs = 0  # インスタンス数を追跡するクラス変数

    def __init__(self, name, age):
        self.name = name  # インスタンス変数
        self.age = age    # インスタンス変数
        Dog.number_of_dogs += 1  # 新しいインスタンスが生成されるたびにカウント

    def bark(self):
        return f"{self.name} says woof!"

# Dogクラスのインスタンスを生成
dog1 = Dog("Buddy", 3)
dog2 = Dog("Lucy", 5)
dog3 = Dog("Max", 2)

# クラス変数 number_of_dogs にアクセス
print(f"現在の犬の数: {Dog.number_of_dogs}")  # 出力: 現在の犬の数: 3

説明

  • クラス変数 number_of_dogs:
  • すべての Dog インスタンスで共有される属性です。
  • 新しい Dog インスタンスが生成されるたびに、この変数が1ずつ増加します。

  • インスタンス生成時の処理:

  • __init__ メソッド内で、Dog.number_of_dogs を増加させています。これにより、生成された犬の数を追跡できます。

注意点:ミュータブルなクラス変数

クラス変数がミュータブル(変更可能)なデータ型(リストや辞書など)である場合、予期せぬ動作が発生することがあります。これは、クラス変数がすべてのインスタンスで共有されるためです。

サンプルコード

class Dog:
    tricks = []  # クラス変数としてリストを定義

    def __init__(self, name):
        self.name = name  # インスタンス変数

    def add_trick(self, trick):
        self.tricks.append(trick)  # クラス変数を変更

# Dogクラスのインスタンスを生成
dog1 = Dog("Buddy")
dog2 = Dog("Lucy")

# 各インスタンスでトリックを追加
dog1.add_trick("roll over")
dog2.add_trick("play dead")

# クラス変数 tricks を確認
print(Dog.tricks)   # 出力: ['roll over', 'play dead']
print(dog1.tricks)  # 出力: ['roll over', 'play dead']
print(dog2.tricks)  # 出力: ['roll over', 'play dead']

説明

  • クラス変数 tricks は、すべてのインスタンスで共有されます。
  • dog1dog2 の両方が同じ tricks リストを操作しているため、追加されたトリックがすべてのインスタンスで見られます。
  • ミュータブルなクラス変数を使用する際は、この動作を理解し、意図しない共有を避けるために注意が必要です。

まとめ

  • クラス変数は、クラス全体で共有されるデータを保持します。これにより、共通の情報を効率的に管理できます。
  • クラス変数は、クラス名を通じて直接アクセスおよび変更することができます。インスタンスを通じてアクセスすることも可能ですが、すべてのインスタンスで共有される点に注意が必要です。
  • ミュータブルなクラス変数を使用する際は、予期せぬ動作を避けるために慎重に設計する必要があります。
  • クラス変数とインスタンス変数を適切に使い分けることで、より効率的で整理されたコードを書くことができます。

実際にPythonコードを書いてクラス変数を操作し、クラス全体でデータを共有する方法を試すことで、クラス変数の概念とその使い方をより深く理解しましょう。

実践例:学生クラスでのクラス変数の利用

以下に、Student クラスでクラス変数を使用して、学生の総数を追跡する例を示します。

class Student:
    # クラス変数
    total_students = 0

    def __init__(self, name, grade):
        self.name = name    # インスタンス変数
        self.grade = grade  # インスタンス変数
        Student.total_students += 1  # 新しいインスタンスが生成されるたびにカウント

    def display_info(self):
        print(f"学生名: {self.name}, 成績: {self.grade}")

    @classmethod
    def get_total_students(cls):
        return cls.total_students

# Studentクラスのインスタンスを生成
student1 = Student("佐藤", "A")
student2 = Student("鈴木", "B")
student3 = Student("高橋", "A")

# 各インスタンスの情報を表示
student1.display_info()  # 出力: 学生名: 佐藤, 成績: A
student2.display_info()  # 出力: 学生名: 鈴木, 成績: B
student3.display_info()  # 出力: 学生名: 高橋, 成績: A

# クラス変数 total_students をクラスメソッドで取得
print(f"総学生数: {Student.get_total_students()}")  # 出力: 総学生数: 3

説明

  • クラス変数 total_students:
  • Student クラスのすべてのインスタンスで共有される変数です。
  • 新しい Student インスタンスが生成されるたびに、この変数が1ずつ増加します。

  • クラスメソッド get_total_students:

  • クラス変数 total_students を取得するためのメソッドです。
  • @classmethod デコレーターを使用して定義されています。

  • オブジェクト生成とクラス変数の更新:

  • student1, student2, student3 の各インスタンスが生成されると、total_students が3に増加します。

  • クラスメソッドの呼び出し:

  • Student.get_total_students() を呼び出すことで、総学生数を取得できます。

参考資料

出力結果: