読者です 読者をやめる 読者になる 読者になる

<Python> static / class / instance(self) での変数の参照

Pythonで、
1. スタティックメソッドstatic method
2. クラスメソッドclass method
3. ふつー、、インスタンスメソッドinstance method つまり、self
の時の変数variablesの参照を確認してみた。

まずは下記のようなクラスclass作成。

In [122]: class Bbb:
     ...:     a = 1
     ...:     b = 1
     ...:     c = 1
     ...: 
     ...:     @staticmethod
     ...:     def static_up(b):
     ...:         Bbb.a = Bbb.a + 10
     ...:         Bbb.b = b
     ...:         c = 2
     ...:    
     ...:     @classmethod
     ...:     def class_up(cls, b):
     ...:         cls.a = cls.a + 100
     ...:         cls.b = b
     ...:         c = 3
     ...:    
     ...:     def self_up(self, b):
     ...:         self.a = self.a + 1000
     ...:         self.b = b
     ...:         c = 4
     ...:   
     ...:     @staticmethod
     ...:     def static_print():
     ...:         print('a={a} b={b} c={c}'.format(a=Bbb.a, b=Bbb.b, c=Bbb.c))
     ...: 
     ...:     @classmethod
     ...:     def class_print(cls):
     ...:         print('a={a} b={b} c={c}'.format(a=cls.a, b=cls.b, c=cls.c))
     ...: 
     ...:     def self_print(self):
     ...:         print('a={a} b={b} c={c}'.format(a=self.a, b=self.b, c=self.c))
     ...:         

で、まずは、クラス変数の初期値確認。

In [123]: Bbb.static_print()
a=1 b=1 c=1

In [124]: Bbb.class_print()
a=1 b=1 c=1

In [125]: Bbb.self_print()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-125-15913240ab6a> in <module>()
----> 1 Bbb.self_print()

TypeError: self_print() missing 1 required positional argument: 'self'

インスタンスinstanceしていないので、selfはエラーを吐く。

で、インスタンス化。
で、インスタンス変数を確認。

In [126]: bbb1 = Bbb()

In [127]: bbb1.static_print()
a=1 b=1 c=1

In [128]: bbb1.class_print()
a=1 b=1 c=1

In [129]: bbb1.self_print()
a=1 b=1 c=1

で、staticmethodで変数をアップ。

In [130]: bbb1.static_up(2)

In [131]: bbb1.static_print()
a=11 b=2 c=1

In [132]: bbb1.class_print()
a=11 b=2 c=1

In [133]: bbb1.self_print()
a=11 b=2 c=1

次に、classmethodで変数をアップ。

In [134]: bbb1.class_up(3)

In [135]: bbb1.static_print()
a=111 b=3 c=1

In [136]: bbb1.class_print()
a=111 b=3 c=1

In [137]: bbb1.self_print()
a=111 b=3 c=1

static class selfとも返しは同じ。
で、selfで変数をアップ。

In [138]: bbb1.self_up(4)

In [139]: bbb1.static_print()
a=111 b=3 c=1

In [140]: bbb1.class_print()
a=111 b=3 c=1

In [141]: bbb1.self_print()
a=1111 b=4 c=1

ここで、違いが発生。
selfは、クラス変数に影響しない。別物。

ちなみに、この時、クラスそのものの変数を見ると、、、

In [142]: Bbb.static_print()
a=111 b=3 c=1

In [143]: Bbb.class_print()
a=111 b=3 c=1

と、いうことで、インスタンスの関数でクラス変数を弄っても、クラス変数が変わる。

クラスでクラス変数を変えると、

In [144]: Bbb.static_up(5)

In [145]: Bbb.static_print()
a=121 b=5 c=1

In [146]: bbb1.static_print()
a=121 b=5 c=1

In [147]: bbb1.self_print()
a=1111 b=4 c=1

クラスでもインスタンスでもクラス変数が変わる。

クラスのすぐ下に記述した変数がクラス変数。
関数からその変数を参照するには、、、
関数が、クラス内で一階層下に位置するので、上位階層を指定する必要がある。
それが、Bbb.*だったり、cls.*
インスタンス変数とクラス変数は別物だが、クラスの指定cls.*を積極的にしない限り、インスタンスでは、クラス変数は隠れる。
っぽい。