クラス変数の概念
4.2 クラス変数の概念
実はクラス内で使える変数には、インスタンス変数以外にも、クラス変数というものがあり、クラス内の変数はインスタンス変数とクラス変数の二つに分類することができます。
クラス変数とは、クラス内でかつメソッドの外で宣言される変数のことを意味し、インスタンス変数以外の変数と覚えるとわかりやすいかもしれません。
またクラス変数に関しては、宣言時には「self.変数名」という形式は用いず、そのまま「変数名 = ~」という形式を用います。
書式:クラス変数の宣言
4.2.1 クラス変数の特徴①:アクセス方法
ではクラス変数を理解するにあたり、クラス変数へのアクセス方法を確認していきましょう。
1. クラス外からアクセスする場合
インスタンス変数は、クラス外からアクセスする場合、インスタンスを介することでアクセスすることができましたが、クラス変数はインスタンスを生成しなくても、直接、アクセスすることができます。
またクラス変数は、インスタンスを介してアクセスすることもできます。
書式:クラス変数へのアクセス(クラス外)
クラス外からクラス変数へアクセスする方法は「クラス名」の後に「.」をつけてアクセスしたいクラス変数を記述します。
オブジェクトの生成が必要ない点がポイントになります。
凡例
class Sample: #クラス変数の宣言 cls = 'クラス変数' def __init__(self,ins): self.ins = ins #クラス変数の呼び出し #直接呼び出した場合 print('直接アクセス:',Sample.cls) #インスタンス生成した場合 sample1 = Sample print('インスタンス生成からのアクセス:',sample1.cls)
実行結果
直接アクセス: クラス変数 インスタンス生成からのアクセス: クラス変数
凡例から直接アクセスしても、インスタンス生成した上でアクセスしてもクラス変数へアクセスできることがわかります。凡例のイメージを図にすると以下の通りになります。
図 4.2.1: クラス変数へのアクセス
図のイメージの通り、クラス変数はインスタンス変数と違い、インスタンスに含まれているというより、生成元であるクラスに含まれています。
そのためインスタンスを介してアクセスする場合でも、クラスからアクセスした値が取得されます。
2. クラス内部からアクセスする場合
続いてクラス内部からクラス変数へアクセスする方法を説明します。
書式:クラス変数へのアクセス(クラス内)
クラス内部(メソッド内)からクラス変数へアクセスするためには、「self」または「クラス名」の後に「.」をつけてアクセスしたいクラス変数を記述します。
書式:クラス変数へのアクセス(クラス内)
クラス内部(メソッド内)からクラス変数へアクセスするためには、「self」または「クラス名」の後に「.」をつけてアクセスしたいクラス変数を記述します。
class クラス名: クラス変数名 = 値 def __init__(self,引数,…): … def メソッド名(self) print(self.クラス変数名) print(クラス名. クラス変数名)
凡例
class Sample: #クラス変数の宣言 cls = 'クラス変数' def __init__(self,ins): self.ins = ins def callCls(self): print('クラス内からアクセス①:',self.cls) print('クラス内からアクセス②:',Sample.cls) #メソッドを介してクラス変数へアクセス sample1 = Sample('') sample1.callCls()
実行結果
クラス内からアクセス①: クラス変数 クラス内からアクセス②: クラス変数
凡例からメソッドから呼び出す場合、「self.クラス変数名」と「クラス名.変数名」のどちらでアクセスしても同じ値が取得できることがわかります。
また凡例のイメージを図にすると以下の通りになります。
図 4.2.2: クラス内部からクラス変数へのアクセス
4.2.2 クラス変数の特徴②:インスタンス間で共通した値を保持する
インスタンス変数はインスタンスごとに異なる値を持たせることができましたが、クラス変数は別々の値を持たせるのには適しません。
インスタンスを介してクラス変数にアクセスした場合でも、結局、インスタンス生成元のクラスを介してクラス変数にアクセスすることになり、クラス変数はインスタンス間で共通の値を保持することになるからです。
図 4.2.3:インスタンスごとのクラス変数へのアクセス
4.2.3 クラス変数の特徴を確認するためのプログラム
続いて共通のクラスから異なるインスタンスを生成し、それぞれインスタンスを介してクラス変数に代入した上で、クラス変数の値を出力した場合、どうなるのかを確認しましょう。
ソース・フォルダー: /Desktop/Python基礎講座
ファイル名: 第4章.ipynb
アクセスURL: http://localhost:8888/notebooks/Desktop/Python基礎講座/第4章.ipynb
class Sample: #クラス変数の宣言 cls = 'クラス変数' def __init__(self,ins): self.ins = ins #インスタンスの生成 sample1 = Sample sample2 = Sample #sample1からクラス変数の呼び出し sample1.cls = 'smp1' print('sample1:',sample1.cls) #sample2からクラス変数の呼び出し sample2.cls = 'smp2' print('sample2:',sample2.cls) #sample1からクラス変数の呼び出し print('sample1:',sample1.cls)
実行結果
sample1: smp1 sample2: smp2 sample1: smp2
解説
1~6行目で定義されているSampleクラスでは、クラス変数clsと、コンストラクタの中にインスタンス変数insが宣言させています。
class Sample: #クラス変数の宣言 cls = 'クラス変数' def __init__(self,ins): self.ins = ins
9、10行目では、Sampleクラスからそれぞれsample1、sample2と異なるインスタンスが生成されており、13行目ではインスタンスsample1を介して、クラス変数clsに「smp1」を代入し、14行目ではsample1を介してclsにアクセスし、値を出力しています。
#sample1からクラス変数の呼び出し sample1.cls = 'smp1' print('sample1:',sample1.cls)
図 4.2.4: クラス変数への代入
続いて17行目では、sample2を介して、クラス変数clsに「smp2」を代入し、18行目ではsample2を介してclsにアクセスし、値を出力しています。
sample2.cls = 'smp2' print('sample2:',sample2.cls)
図 4.2.5: クラス変数への代入②
最後に今度は、クラスcls変数の値を変えず、また21行目でsample1を介してclsにアクセスし、値を出力しています。
print('sample1:',sample1.cls)
図 4.2.6: 異なるインスタンスからクラス変数の値へアクセス
クラス変数はインスタンス間で共通の値を保持するため、17行目でsample2を介して設定した値がそのままclsに格納されており、このような出力結果になります。
4.2.4 インスタンス変数のインスタンス間における独立を確かめるプログラム
クラス変数はインスタンス間で共通した値を持つことがわかりました。一方、インスタンス変数はインスタンスごとに独立しているため、インスタンスを介してインスタンス変数を変更しても、他のインスタンスのインスタンス変数に影響が及ばないはずです。
そこでインスタンスを介してインスタンス変数を変更した場合、他のインスタンスのインスタンス変数に影響が及ばないか確認するプログラムを確認しましょう。
ソース・フォルダー: /Desktop/Python基礎講座
ファイル名: 第4章.ipynb
アクセスURL: http://localhost:8888/notebooks/Desktop/Python基礎講座/第4章.ipynb
class Sample: def __init__(self,name): self.name = name def nameCall(self): print('お名前:',self.name) #インスタンスの生成 sample1 = Sample('田中') sample2 = Sample('加藤') print('【変更前のインスタンス変数の値】') #メソッドを介してインスタンス変数の呼び出し① sample1.nameCall() sample2.nameCall() #インスタンス変数の変更 sample1.name = '佐藤' sample2.name = '吉田' print('【変更後のインスタンス変数の値】') #メソッドを介してインスタンス変数の呼び出し② sample1.nameCall() sample2.nameCall()
実行結果
【変更前のインスタンス変数の値】 お名前: 田中 お名前: 加藤 【変更後のインスタンス変数の値】 お名前: 佐藤 お名前: 吉田
解説
1~7行目で定義されているSampleクラスでは、コンストラクタの中にインスタンス変数nameが宣言させており、またインスタンス変数nameを出力するための、メソッド「nameCall」が定義されています。
class Sample: def __init__(self,name): self.name = name def nameCall(self): print('お名前:',self.name)
10行目では、引数を「田中」にSampleクラスからsample1というインスタンスを生成し、11行目でも引数を「加藤」にSampleクラスからsample2というインスタンスを生成しています。
引数の値(田中、加藤)は、そのまま各インスタンスのインスタンス変数へ値が代入されます。
sample1 = Sample('田中') sample2 = Sample('加藤')
15行目ではsample1を介して「nameCall」メソッドを呼び出しており、16行目ではsample2を介して「nameCall」メソッドを呼び出しています。
「nameCall」は各インスタンスのインスタンス変数を呼び出すメソッドですので、「お名前: 田中」、「お名前: 加藤」という出力が表示されます。
sample1.nameCall() sample2.nameCall()
10、11、15、16行目のイメージをまとめると下記の図の通りになります。
図 4.2.7: インスタンスごとのインスタンス変数へのアクセス
続いて19行目では、sample1のインスタンス変数nameに「佐藤」という値を代入し、20行目ではsample2のインスタンス変数nameに「吉田」という値を代入します。
sample1.name = '佐藤' sample2.name = '吉田'
そして24、25行目で再び、「nameCall」メソッドを介して、sample1、sample2の各々のインスタンス変数nameの値を出力しています。
sample1.nameCall() sample2.nameCall()
19、20、24、25行目のイメージをまとめると以下の図の通りになります。
図 4.2.8: インスタンスごとのインスタンス変数へのアクセス②
各インスタンスからインスタンス変数へアクセスし値を変えてますが、出力結果を見ると他のインスタンスの値に影響を与えないことがわかるので、インスタンス変数は独立して使用することができることがわかります。
以上、インスタンス変数、クラス変数の違いについて説明しました。双方の違いをまとめると、以下の表の通りになります。
ポイント
- クラス変数はクラス自身に関連付けられる為、インスタンスを生成せずに直接アクセスできるが、クラス変数はインスタンス間で共通である。