__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が作られている。