python のクラス変数とインスタンス変数で、クラス変数の内容を変更したときにインスタンスに与える影響について確認してみました。
クラス変数:
クラス変数はそのクラスのすべてのインスタンスによって共有される属性やメソッドのためのものです
インスタンス変数:
インスタンス変数はそれぞれのインスタンスについて固有のデータのためのもの
検証のために Dog
クラスを用意します。
class Dog:
tricks = []
kind = 'pug'
def __init__(self, name):
self.name = name
def add_trick(self, trick):
self.tricks.append(trick)
def change_kind(self, kind):
self.kind = kind
Dog
クラスからインスタンスを 2 つ作ります。
fibo = Dog('Fibo')
buddy = Dog('Buddy')
ここからクラス変数の挙動を確認してみます。クラス変数はすべてのインスタンスに共有されているので、クラス変数 trick
に対して fibo
インスタンスでの変更が buddy
インスタンスに共有されるか確認します。
fibo.add_trick('roll over')
print(buddy.tricks)
# ['roll over']
また、Dog
クラスをインスタンス化させなくてもすべてのインスタンスに対して影響を与えています。
Dog.tricks.append('stay')
print('fibo:', fibo.tricks)
# fibo: ['roll over', 'stay']
print('buddy:', buddy.tricks)
# buddy: ['roll over', 'stay']
クラス変数 kind
も検証してみます。change_kind
メソッドを呼び出して kind
の値を変更し別のインスタンスで変更が反映されるか確認します。
fibo.change_kind('golden retriever')
print('fibo:', fibo.kind)
# fibo: golden retriever
print('buddy:', buddy.kind)
# buddy: pug
fibo
インスタンスでの変更は buddy
インスタンスに影響を及ぼしませんでした。change_kind
メソッドではクラス変数の kind
ではなく インスタンス変数の kind
に変更を加えているのでした。クラス変数とインスタンス変数が同じ名前の場合は、インスタンス変数が優先されます。
def change_kind(self, kind):
self.kind = kind
クラス変数 kind
を変更してみます。
Dog.kind = 'bulldog'
各インスタンスの状態を確認します。
print('fibo:', fibo.kind)
# fibo: golden retriever
print('buddy:', buddy.kind)
# buddy: bulldog
fibo
インスタンスの方は change_kind
メソッドを使用してインスタンス変数を定義したのでインスタンス変数を取得しているのに対して、buddy
インスタンスはインスタンス変数 kind
が存在しないのでクラス変数 kind
を参照し、Dog.kind
での変更の影響を受けております。
最後に、オブジェクトの属性を確認します。
print(vars(fibo))
# {'name': 'Fibo', 'kind': 'golden retriever'}
print(vars(buddy))
# {'name': 'Buddy'}