Pythonのdataclass
下のほうに書いたインスタンス変数とクラス変数の件が頭の中にありちょっと混乱したので整理します。
Python3.7?以降ではクラスを@dataclass
でアノテーションすると、自動的に___init__()
が追加されるそうです。
次のsample1.pyだと___init__(self, a:int, b:str)
があるのと同じに扱われます。
sample1.py
@dataclass
class Test:
a:int
b:str
def print(self):
print(self.a)
print(self.b)
t = Test(1,'abc') # ⇒ t=Test()だとエラーになる。__init__()の引数が足りないため。
t.print() # ⇒ 1 'abc'と出力される
Pythonのクラス変数とインスタンス変数
Pythonのクラスの変数には
・クラス変数
・インスタンス変数
の2種類があります。
下記のsample.pyのようにclass定義の直下にa:int
やb:str
のように書いているのが「クラス変数」です。
クラス変数は全インスタンスで共通の値が保持されます。詳細は後述します。
sample1.py
class Test:
a:int
b:str
def printTest(self):
print(self.a)
print(self.b)
また、下記のように__init__()で初期化しているのが「インスタンス変数」です。インスタンス変数はクラスをインスタンス化した変数それぞれで保持します。
sample2.py
class Test:
def __init__(self, a:int, b:str):
self.a = a
self.b = b
def printTest(self):
print(str(self.a))
print(self.b)
また、init()を使わずともインスタンス変数は定義可能で、以下のようにインスタンス.変数=値で設定ができます。
sample3.py
class Test:
def printTest(self):
print(self.a)
print(self.b)
t=Test()
t.a=987
t.b='QWERTY'
実際に値を設定して出力すると以下のような動きになります。クラス変数は全インスタンスに共通なのが分かると思います。
ということでクラス変数の変更は要注意です。
sample4.py
class Test:
a:int
b:str
def printTest(self):
print(self.a)
print(self.b)
Test.a=10
Test.b='xyz'
t1 = Test()
t1.printTest() # ⇒ 10 'xyz'と出力される(クラス変数)
t1.a = 20
t1.b = 'def'
t1.printTest() # ⇒ 20 'def'と出力される(インスタンス変数が優先される)
t2 = Test()
t2.printTest() # ⇒ 10 'xyz'と出力される(クラス変数)