オブジェクト指向プログラミング(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
インスタンスで同じ値を持ちます。
インスタンス変数 name
と age
:
クラス変数は、クラス名を通じて直接アクセスすることも、インスタンスを通じてアクセスすることもできます。ただし、インスタンスを通じてアクセスした場合でも、クラス変数はすべてのインスタンスで共有されます。
# 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
を通じて直接アクセスできます。dog1
と dog2
を通じてもアクセスできますが、どちらも同じクラス変数を参照しています。クラス変数を使用して、クラス全体で共有される情報を管理する例を見てみましょう。例えば、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
は、すべてのインスタンスで共有されます。dog1
と dog2
の両方が同じ 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()
を呼び出すことで、総学生数を取得できます。