クラス属性を使用してインスタンス固有のデータにする予定のデフォルト値を提供する主な問題は、値が変更されるまでデフォルト値がクラスのすべてのインスタンス間で共有されることです。例えば:
class Foo(object):
a = []
foo1 = Foo()
foo2 = Foo()
foo1.a.append(123)
foo1.a # [123]
foo2.a # [123]
ただし、以下は期待どおりに機能します。
class Bar(object):
a = 123
bar1 = Bar()
bar2 = Bar()
bar1.a = 456
bar2.a # 123
この手法を使用しているときにこの問題を回避するには、不変値であるデフォルトを設定するためにのみ使用する必要があります。(例: 数値、文字列、タプル…)
Python がこのように動作する理由は、次のように属性にアクセスする場合です。
foo.bar
thenbar
が最初にオブジェクト内で検索されますfoo
。名前がオブジェクト (つまり ) で見つからない場合、名前はfoo.__dict__
そのオブジェクトの型で検索されます。たとえば、このメカニズムはメソッド検索の仕組みの一部です。(オブジェクトの を見ると、__dict__
そのメソッドが存在しないことがわかります。)
その他のマイナーな問題は、インスタンス固有であることを意図している場合に、型オブジェクトを介してデフォルトを公開することです。また、クラス固有の属性 (定数など) の定義がデフォルトと混在している場合。前者の当然の帰結は、class 属性に代入することによって、まだ値を変更していないすべてのオブジェクトに対して、後でデフォルトの値を再定義できるようにすることです。(これは便利な場合もあれば、混乱を招く場合もあります。変更可能な「グローバル」変数に対する同じ予防措置が適用されます。)