dictのインスタンスにattributeがセットできない(3)
だいぶ見えてきた。属性を設定する方法は4通りあると思う(まだあるかもしれない)。
>>> class Bar(object): ... def __setattr__(self, k, v): ... print '__setattr__() called' ... >>> b = Bar() >>> b.a = 1 # 1通り目 __setattr__() called >>> setattr(b, 'b', 2) # 2通り目 __setattr__() called >>> b.__setattr__('c', 3) # 3通り目 __setattr__() called >>> b.__dict__['d'] = 4 # 4通り目 >>> b.__dict__ {'d': 4} >>> b.a Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Bar' object has no attribute 'a' >>> b.b Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Bar' object has no attribute 'b' >>> b.c Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Bar' object has no attribute 'c' >>> b.d 4 >>>
自分で定義したクラスに__setattr__をオーバーライドしてみると、__dict__に直接属性を設定しない限り実際の属性は設定されない。つまり、デフォルトの__setattr__メソッドは、__dict__を直接操作する以外の方法で属性を設定すると implicit に呼び出され、その実装の中で__dict__を操作していると予測できる。
つまり、__dict__を属性から外し、__setattr__の実装を調整すれば、属性を設定できないようにすることが可能である。この方法で組み込み型のクラス、インスタンス共に属性の設定をできなくしているのではないだろうか。これは、クラスと(カスタム?)メタクラスの実装を調整すれば可能だと思う。実際どうなっているかは、ソースを読んで確認してみようと思う。
ちなみに、Cookbookを読んで分かったのだが、__slots__は、大量のインスタンスを作成場合に無駄なメモリを減らすという用途で使用するらしく、属性の制限という用途では使用しないらしい。