以下は、一般的なクラス定義です。
>>> class Point(object): ... def __init__(self): ... self.x = 0 ... self.y = 0 ... # クラスのサイズを取得 >>> import sys >>> sys.getsizeof(Point) 492このクラスのサイズは 492バイトとなりました。
続いて、クラスの先頭で __slots__ を定義します。__slots__ はリスト(or タプル)で、各要素は使用するアトリビュート名とします。
>>> class Point(object): ... __slots__ = ['x', 'y'] # __slots__を定義 ... ... def __init__(self): ... self.x = 0 ... self.y = 0 ... # クラスのサイズを取得 >>> sys.getsizeof(Point) 428クラスのサイズは 428バイトになりました。
この例では __slots__ を定義することで 64バイト減ったことになります。インスタンスが多数ある場合には(100万個とか)、決して小さくはない減少量と言えます。
ただし、__slots__ には副作用もあります。
通常のクラスではアトリビュートを後から追加することができますが、__slots__ を定義した場合には、__slots__ の要素のアトリビュートしか持てないようになります。
# __slot__を定義したクラスのインスタンス >>> p = Point() # zを追加できない >>> p.z = 0 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Point' object has no attribute 'z' # setattrでもできない >>> setattr(p, 'z', 0) Traceback (most recent call last): File "<stdin>", line 1, inAttributeError: 'Point' object has no attribute 'z'
一方、__slots__ を定義することで、アトリビュートの追加が出来ない代わりに、アトリビュートへのアクセスが高速化されるという利点もあります。
結局、__slots__ を使うべき場面とは、以下の2つを共に満たす場合になります。
- アトリビュートの追加がないクラス
- 多数のインスタンスが予想されるクラス、又は、動作速度が非常に重要なクラス
0 件のコメント:
コメントを投稿