こんにちはPython界のレアキャラです。
dataclassから機能が追加され attrsであった機能が取り込まれました。
以前書いた記事のアップデートをしておこうと思います。
TL;DR
- dataclassにkw_onlyと slotsが入った
- attrsのつかいどころ
- ボイラープレートコードを避けたい.(特にdataclassにない機能を利用したい)
- 今Python3.9 以下を使っているし、今後dataclassを使いたい.
- ドキュメントをきちんと読むと色々書いてある
docs.python.org
kw_only
https://docs.python.org/ja/3.10/glossary.html#term-parameter
キーワード専用フィールドを設定するためのもの.
>>>
>>> @dataclass(kw_only=True)
... class A:
... a: int
... b:int
...
>>> a = A(1,2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: A.__init__() takes 1 positional argument but 3 were given
>>> a = A(a=1,b=2)
>>> a
A(a=1, b=2)
ちなみに1フィールドだけ キーワード専用にしたいときは dataclasses.field
でできる。
>>> from dataclasses import field
>>> @dataclass
... class B:
... x:int
... y:int = field(kw_only=True)
...
>>> B(1,2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: B.__init__() takes 2 positional arguments but 3 were given
>>> B(1,y=2)
B(x=1, y=2)
>>>
ちなみにattrsでは以下のように書く.attrsでは3.9以前のバージョンでも使える.
from attrs import define, field
@define(kw_only=True)
class A:
a: int
b: int
@define
class A:
a: int
b: int = field(kw_only=True)
slots オプション
全俺が欲しかったもの。
以前は明示的に __slots__
をつけないといけなかった。3.10からはこんな感じで書ける
from dataclasses import dataclass
@dataclass
class SlotedMessage:
__slots__ = ["sender", "recipient", "body"]
sender: str
recipient: str
body: str
@dataclass(slots=True)
class SlotedMessage:
sender: str
recipient: str
body: str
以前試した メモリの使用量見てみよう。
masahito.hatenablog.com
ちなみに実行前に pymperをinstallしてほしい。
pip install pympler
from typing import NamedTuple
from pympler import asizeof
from attrs import define
from dataclasses import dataclass
Message = NamedTuple("Message", [("sender", str), ("recipient", str), ("body", str)])
@dataclass
class DataClassMessage:
sender: str
recipient: str
body: str
@dataclass(slots=True)
class SlotedMessage:
sender: str
recipient: str
body: str
@define(auto_attribs=True, slots=True, weakref_slot=False)
class AttrsMessage:
sender: str
recipient: str
body: str
if __name__ == "__main__":
d = {
"sender": "sender@exmaple.com",
"recipient": "recipient.example.com",
"body": "Hello, World!",
}
message = Message(**d)
simple_data = DataClassMessage(**d)
slotted = SlotedMessage(**d)
attrs = AttrsMessage(**d)
print(
"NamedTuple %d, Dataclass %d, Slotted dataclass %d, attrs %d"
% asizeof.asizesof(message, simple_data, slotted, attrs)
)
% python aaa.py
NamedTuple 272, Dataclass 528, Slotted dataclass 56, attrs 56
ここまでくると attrsのweakre_slots も入れて欲しかった気がする.
久しぶりにdataclassのドキュメントを読み返すことで発見がたくさんありました。
Python 開発者、ドキュメント書いてくれている皆様に感謝!