Python クラス #3

株式会社リュディアです。今回も引き続きクラスについてまとめていきます。

前回までの Python クラスについてのまとめへのリンクは以下を参考にしてください。

今回もクラス変数インスタンス変数についてまとめていきます。前回までのまとめでクラス変数はクラスの定義に対して1つだけ、インスタンス変数はインスタンスごとにもつ変数としました。またクラス変数にアクセスするにはクラス名からアクセスすることも記載しました。

しかし実際のコーディングでインスタンスからクラス変数にアクセスしてしまうミスはそれなりに存在し、また Python 処理系自体もそれをエラーとして検出しないという厄介な問題を抱えています。今回は具体例を通して注意点についてまとめてみます。

まず以下の例を見てください。

class VegetableClass():
    num_of_types = 800
    def __init__(self, c):
       self.color = c

lettuce = VegetableClass('green')
tomato = VegetableClass('red')

print(VegetableClass.num_of_types)
print(lettuce.num_of_types)
print(tomato.num_of_types)

# 800
# 800
# 800

最初の print 文ではクラス名から num_of_types にアクセスしていますが、後の2つはインスタンス lettuce, tomato を通して num_of_types にアクセスしています。エラーも出ませんしすべて同じ値 800 であることを確認できます。ここまで問題ないです。では、次の例を見てください。

class VegetableClass():
    num_of_types = 800
   def __init__(self, c):
       self.color = c

lettuce = VegetableClass('green')
tomato = VegetableClass('red')

print(VegetableClass.num_of_types)
print(lettuce.num_of_types)
print(tomato.num_of_types)

lettuce.num_of_types = 1200

print(VegetableClass.num_of_types)
print(lettuce.num_of_types)
print(tomato.num_of_types)

# 800
# 800
# 800
#
# 800
# 1200
# 800

lettuce から num_of_types を 1200 に変更した後の表示に注意してください。lettuce.num_of_types は 1200 になっていますが、VegetableClass.num_of_types, tomato.num_of_types はともに 800 のままです。では num_of_types の ID を調べてみましょう。次の例を見てください。

class VegetableClass():
    num_of_types = 800
   def __init__(self, c):
       self.color = c

lettuce = VegetableClass('green')
tomato = VegetableClass('red')

print(id(VegetableClass.num_of_types), VegetableClass.num_of_types)
print(id(lettuce.num_of_types), lettuce.num_of_types)
print(id(tomato.num_of_types), tomato.num_of_types)

lettuce.num_of_types = 1200

print(id(VegetableClass.num_of_types), VegetableClass.num_of_types)
print(id(lettuce.num_of_types), lettuce.num_of_types)
print(id(tomato.num_of_types), tomato.num_of_types)

# 2268480275120 800
# 2268480275120 800
# 2268480275120 800
# 2268480275120 800
# 2268480274896 1200 <- これだけ ID が異なる
# 2268480275120 800

オブジェクトの ID を調べるとすぐわかりますね。lettuce.num_of_types のみオブジェクト ID が異なります。つまり他のオブジェクトを指していることになります。

何が起こっているのか、というと Python ではインスタンス変数をインスタンスを通して作成することができます。そのため lettuce.num_of_types = 1200 というのは、既にあるクラス変数 num_of_types にアクセスしているのではなく新規のインスタンス変数 num_of_types を作成して、その値を 1200 に設定しているに過ぎないわけです。

結論としてクラス変数はクラス名を通してアクセスすることを徹底するしかありません。ご注意ください。

Python のクラスに関するまとめの続きは以下からどうぞ。

では、ごきげんよう。



この記事が気に入ったらサポートをしてみませんか?