見出し画像

Python学習メモ(クラス変数とインスタンス変数)

Python3エンジニア認定基礎試験にむけてぼちぼちと勉強を進めている今日この頃ですが、模擬試験で引っかかった問題があったのでメモを残します。

内容はクラス変数とインスタンス変数。結果から言うと今までpyxelで遊んでいたときとかに使っていたのは全てインスタンス変数で、クラス変数というのは意識したこともありませんでした。簡単な実例とともにメモしておきます。

# -*- coding: utf-8 -*-

class Num_test:
   num_list = []
   def __init__(self, n):
       self.num_list.append(n)
   def Show_num(self):
       print(self.num_list)

Num1 = Num_test(1)

Num1.Show_num()

Num2 = Num_test(2)

Num2.Show_num()

▲こんなコードがあったとします。Num_testというクラスがあり、中にクラス変数num_listがあります。このクラスはインスタンス化されたときに__init__関数が呼び出され、引数nがself.num_listに追加されます。また、self.num_listを表示するShow_num関数もあります。

Num_testクラスに引数1を与えてインスタンス化したものをNum1とします。Num1のShow_num関数を呼び出すとどうなるでしょうか?

[1]

[1]が出力されました。まあそりゃそうだろうって感じですね。同様にNum_testクラスに引数2を与えてインスタンス化したものをNum2とします。Num2のShow_num関数を呼び出すと、さて今度はどうなるでしょうか?[2]が表示される感じしません?

[1, 2]

[1, 2]が表示されました。はて?Num1とNum2はインスタンスとして違うのになんで1が付いてくるのか?

それはnum_listがクラス変数として定義されているからです。その後__init__関数でselfをつけてインスタンス変数として定義した風になってはいますが、これはselfを通してクラス変数にアクセスしていたのでした(多分)。

class Num_test:
  def __init__(self, n):
      self.num_list = []
      self.num_list.append(n)
  def Show_num(self):
      print(self.num_list)

Num1 = Num_test(1)

Num1.Show_num()

Num2 = Num_test(2)

Num2.Show_num()

▲このようにselfをつけて__init__関数内でnum_listを定義してやるとインスタンス変数となるので、結果は以下のようになります。

[1]
[2]

▲Num1とNum2のインスタンスで変数の値は共有されていません。

※ちなみにこれはクラス変数に関するよくあるミスのようで、このような定義の仕方は推奨されていません。クラス変数と同じ名前でインスタンス変数を作るなってことで良いのかな。どっちの変数にアクセスしてるのか分かりにくくなりますもんね。

class Num_test:
  num_list = []
  def __init__(self, n):
      Num_test.num_list.append(n)
  def Show_num(self):
      print(Num_test.num_list)

Num1 = Num_test(1)

Num1.Show_num()

Num2 = Num_test(2)

Num2.Show_num()

▲クラス変数にアクセスするときにはクラス名.クラス変数名ってやるのが流儀みたい。

ここまで読んでいただきありがとうございます!