__slots__

クラス定義で、インスタンスに自由に変数を追加できなくするには、__slots__を指定する。使える変数名をリストで渡す。

>>> class Foo(object):
...     __slots__ = ['foo']
...
>>> f = Foo()
>>> f.foo = 10
>>> f.bar = 20
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute 'bar'
>>>

不便になるだけなので、こんなことはしないほうがいいと思うが、やりたい場合もあるかも。

この機能はそもそも、メモリ節約のためにある。__slots__の指定がないと、インスタンスごとに変数を保存するためのdictが作られる*1。__slots__を指定すると、dictを作らなくなるので、そのぶんメモリを消費しなくなる。

ためしに、上記のような空っぽのクラスのインスタンスを100万個作ってみると、pythonのメモリ消費が

起動直後 7386
__slots__指定なし 44144 約38bytes/インスタンス
__slots__指定あり 19964 約13bytes/インスタンス

という感じ(単位:KB, psコマンドのVSZ値)。

__slots__を指定しつつ、インスタンスに自由に変数を追加できるようにするには、__slots__に'__dict__'を加える。

>>> class Bar(object):
...     __slots__ = ['foo', '__dict__']
...
>>> b = Bar()
>>> b.foo = 10
>>> b.bar = 20
>>>

なお、new-styleクラスでないと効果はない。

>>> class Foo:
...     __slots__ = ['foo']
...
>>> f = Foo()
>>> f.foo = 10
>>> f.bar = 20
>>>

詳しくはPythonリファレンスのhttp://www.python.jp/doc/2.4/ref/slots.htmlをどうぞ。というか、ほぼリファレンスをぱくっただけです。

*1:実際は__dict__と__weakref__の2つのdictが作られている。