Pythonでクラスを作っていて、クラス変数が恐ろしいことに気づいた。
例えば、以下のようなクラスを作ってみる。
class Hoge: def __init__(self): self.a = 1 def foo(self): self.b = 2
これのインスタンスを作ると、aやbの読み書きができるのは理解できる。
>>> hoge = Hoge() >>> hoge.a 1 >>> hoge.b AttributeError: Hoge instance has no attribute 'b' >>> hoge.foo() >>> hoge.b 2
このあと、hoge.aやhoge.bを書き換えられるのも(ややセキュアではないが)分からなくはない。問題はこの後だ。
>>> hoge.c = 3 >>> hoge.c 3
クラスを定義した時には作っていなかった変数であるcをいとも簡単に追加でき、読み書き可能なのである。「便利じゃん」という意見もあるだろうが、何かしら代入するときに変数名を打ち間違えても(上のコードではbと間違えてcと打った時)、エラーも出さずに進んでしまうという恐怖。
さらに問題はこのあとで、
>>> hoge.foo = 4 >>> hoge.foo 4 >>> hoge.foo() TypeError: 'int' object is not callable
お分かりいただけるだろうか、クラス内で定義されていた関数名と同じ名前の変数を定義でき、あろうことか上書きしてしまった。上書き自由にもほどがある。
以上のコードはUbuntu11.10上のPython 2.7.1での動作だが、Python 3系列ではどうなっているのか大変気になる。
ちなみにRubyでは、クラス内の変数にアクセするためにはattr_accessorやattr_readerに登録しなければならないので上記のようなことは起こり得ないし、関数を変数で上書きするなんてこともできない。
追記
Python3.2で試しても同じ結果でした。どういう思想でこうなっているんだろう?