dataclassと __slots__ について調べた
対象バージョン Python 3.7以降
TL;DR
- dataclassでも
__slots__
を使える __slots__
をつかうとpropertyの追加ができなくなる(自由度が下るが、コードをおいやすくなる)
slots とは
__slots__
を使うと、(プロパティのように) データメンバを明示的に宣言し、 (明示的に__slots__
で宣言しているか親クラスに存在しているかでない限り)__dict__
や__weakref__
を作成しないようにできます。__dict__
を使うのに比べて、節約できるメモリ空間はかなり大きいです。 属性探索のスピードもかなり向上できます。
ということらしい。
dataclassの動作
dataclassを自分で使うときは私の用途だと関数の返り値/引数とかで使うときがおおいのでメモリ空間の節約できると便利だと思ってしらべてみました。 また、データ型の表現で使うときはプロパティの追加ができないほうが便利かなーと。
>>> import dataclasses >>> @dataclasses.dataclass ... class A: ... b: int >>> a = A(1) >>> a.b 1 >>> a.c =2 # propertyを追加できる >>> a.c 2 >>> dir(a) # __dict__ や __weakref__ が作成される ['__annotations__', '__class__', '__dataclass_fields__', '__dataclass_params__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'b', 'c']
というわけでdataclassでは __slots__
が有効ではないみたい。
dataclassの動作を見てる感じだと、__slots__
を有効にするオプションはないみたい
docs.python.org
dataclss with __slots__
www.python.org PEP-557では自動的に追加することは一旦やめる的なことが書かれている。 実際に使うにはこんならしい。
>>> @dataclasses.dataclass ... class B: ... __slots__ = ('b',) # __slots__ 追加 ... b: int ... >>> b = B(2) >>> dir(b) ['__annotations__', '__class__', '__dataclass_fields__', '__dataclass_params__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'b'] >>> b.d =3 # propetyの追加不可 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'B' object has no attribute 'd'
まとめ
ということで dataclassをつかったクラスでも __slots__
を定義すれば設定できる。ただ、これ何回も書くのめんどいので
なんかいも設定するならば attrs 使ったほうがよさそう。明日はattrsを使ったパターンを書こうと思う