オブジェクト(class)の作成-その2
記事の内容
この記事では、オブジェクト作成において、クラス変数を定義する方法を説明します。
クラス変数は、インスタンスを生成していなくても、クラスから直接読み書きすることができます。また、インスタンス変数がインスタンスごとに独立しているのに対し、クラス変数はすべてのインスタンスで共有されます。
***わからない用語があるときは索引ページへ***
この記事のサンプルプログラムは、Python3系をベースとしています。Python2系は、クラス宣言の記述ルールが異なるのでご注意ください。
1.サンプルプログラム
class_ex2.pyは、前の記事のサンプルプログラムで紹介したKagensanクラスに、計算回数を記録するクラス変数keisan_kaisuを追加しています。
##class_ex2.py
##class宣言
class Kagensan:
##クラス変数のセット
keisan_kaisu = 0
##インスタンスコンストラクタの作成
def __init__(self, a, b):
self.x = a
self.y = b
##インスタンスメソッドの作成
def tashizan(self):
wa = self.x + self.y
Kagensan.keisan_kaisu += 1
return wa
def hikizan(self):
sa = self.x - self.y
Kagensan.keisan_kaisu += 1
return sa
##プログラム実行開始位置
print("keisan_kaisu:", Kagensan.keisan_kaisu)
print("\n")
##インスタンスを生成してtasizanメソッドを実行
ins1 = Kagensan(5, 3)
wa = ins1.tashizan()
print("wa:", wa)
print("keisan_kaisu:", ins1.keisan_kaisu)
print("\n")
##インスタンスを生成して引き算メソッドを実行
ins2 = Kagensan(500, 300)
sa = ins2.hikizan()
print("sa:", sa)
print("keisan_kaisu:", ins2.keisan_kaisu)
print("\n")
##クラス変数の書き換えをインスタンスから書き換えてはいけない!!
ins2.keisan_kaisu = 0
print("ins2 keisan_kaisu", ins2.keisan_kaisu)
print("ins1 keisan_kaisu:", ins1.keisan_kaisu)
出力結果
keisan_kaisu: 0
wa: 8
keisan_kaisu: 1
sa: 200
keisan_kaisu: 2
ins2 keisan_kaisu 0
ins1 keisan_kaisu: 2
2.クラス変数の定義
class文直下のプログラムブロックで定義された変数は、クラス変数となります。class_ex2.pyのkeisan_kaisuは、クラス変数となります。
##class宣言
class Kagensan:
##クラス変数のセット
keisan_kaisu = 0
3.クラス変数の呼び出し
クラス変数にアクセスするときは、
<クラス名>.<クラス変数名>
でアクセスします。
class_ex2.pyのKagensanクラスでは、tashizanメソッド、hikizanメソッドが実行されるたびにクラス変数keisan_kaisuの値に1を加算しています。
##インスタンスメソッドの作成
def tashizan(self):
wa = self.x + self.y
Kagensan.keisan_kaisu += 1
return wa
def hikizan(self):
sa = self.x - self.y
Kagensan.keisan_kaisu += 1
クラス変数は、インスタンスを生成していなくてもクラス名で呼び出すことができます。
##プログラム実行開始位置
print("keisan_kaisu:", Kagensan.keisan_kaisu)
出力結果
keisan_kaisu: 0
4.クラス変数はすべてのインスタンスで共有される
クラス変数は、インスタンスからも
<インスタンス名>.<クラス変数名>
の形式でアクセスできます。
インスタンス変数がインスタンスごとに独立しているのに対し、クラス変数はすべてのインスタンスで共有されます。
##インスタンスを生成してtasizanメソッドを実行
ins1 = Kagensan(5, 3)
wa = ins1.tashizan()
print("wa:", wa)
print("keisan_kaisu:", ins1.keisan_kaisu)
print("\n")
##インスタンスを生成して引き算メソッドを実行
ins2 = Kagensan(500, 300)
sa = ins2.hikizan()
print("sa:", sa)
print("keisan_kaisu:", ins2.keisan_kaisu)
print("\n")
class_ex2.pyでは、ins1、ins2の異なるインスタンスからtashizan、hikizanメソッドを実行していますが、クラス変数であるkeisan_kaisuの値が共有され、引き継がれていることがわかります。
出力結果
wa: 8
keisan_kaisu: 1
sa: 200
keisan_kaisu: 2
5.クラス変数をインスタンスから書き換えてはならない!!
上記のように、クラス変数をインスタンスから読み込む場合は問題なく読み込むことができます。
しかし、
<インスタンス名>.<クラス変数名> = <オブジェクト>
で、インスタンスからアクセスしてクラス変数を書き換えると、クラス変数がインスタンス変数として上書きされてしまい、意図せぬ動きになってしまいます。クラス変数をインスタンスから書き換えてはいけません。クラス名を書き換えるときは、必ずクラスから書き換えます。
形式は以下のとおりです。
<クラス名>.<クラス変数名> = <オブジェクト>
クラス宣言のプログラムブロックにおいても、
self.<クラス変数名> = <オブジェクト>
のように、自身を表すインスタンスselfでクラス変数にアクセスして書き換えてはいけません。
class_ex2.pyでは、インスタンスins2からクラス変数keisan_kaisuを書き換えたところ、ins1とins2でクラス変数の共有がおかしくなっています。
##クラス変数の書き換えをインスタンスから書き換えてはいけない!!
ins2.keisan_kaisu = 0
print("ins2 keisan_kaisu", ins2.keisan_kaisu)
print("ins1 keisan_kaisu:", ins1.keisan_kaisu)
出力結果
ins2 keisan_kaisu 0
ins1 keisan_kaisu: 2