LoginSignup
7
10

More than 5 years have passed since last update.

Pythonのクラス変数とインスタンス変数

Last updated at Posted at 2017-06-22

Pythonでクラス変数を定義するには、クラス名の下に変数を宣言するよということになっている。公式ドキュメントでそのように書かれている。

sample.py
   class Sample:
     name = 'name'

   s  = Sample()
   s2 = Sample()

   print(s.name) # 'name'
   print(s2.name) # 'name'

当たり前ですが、どちらも「name」と表示される。

でも、こんな感じでnameを変更した場合、クラス変数ではなくなってしまう。

sample.py
   s  = Sample()
   s2 = Sample()

   s.name = 'aaaa' 

   print(s.name) # 'aaaa'
   print(s2.name) # 'name'

これを実行すると、s.nameはaaaaでs2.nameはnameと表示される。全てのオブジェクトでシェアされるのであれば、s2.nameもaaaaに変わらなければならないはず。

答えとしては文字列はイミュータブルなので、オブジェクトを経由して参照すると自動的にインスタンス変数を作ってくれるということなんだろうか。

でも、Sample.nameにしてみたら、どちらもaaaaに変わった。クラス変数としての特性を持っている。参照元がクラスなのかオブジェクトなのかで、空気読んで解釈しているのかな?

配列や辞書型はミュータブルなので、下記を実行すると変更が伝搬され、どちらのprintも[1,2,3,4]と表示される。同じものを指しているから当たり前。

sample.py
   class Sample:
     a_list = [1,2,3]

   s  = Sample()
   s2 = Sample()
   s.a_list.append(4)
   print(s.a_list)  # [1,2,3,4]
   print(s2.a_list) # [1,2,3,4]

強引にまとめると

イミュータブルはクラスの下に宣言しても自動的にインスタンス変数に切り替わってくれて、ミュータブルはクラス変数のままである、という話でいいのかなこれ。原則、共有するよ。でも、イミュータブルなデータはオブジェクトを経由してアクセスするとインスタンス変数になるよ。

こんな仕様なのかなぁ。

7
10
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
10