公式サイトはこちら
dataclasses - Data Classes - Python 3.10.5 documentation
使用するメリット
- ①可読性が高い
- ②型指定いないとエラーがでる
- ③特殊メソッドが定義される
①可読性が高い
通常のコンストラクタを使うと
class InventoryItem:
"""Class for keeping track of an item in inventory."""
def __init__(self, name: str, unit_price: float, quantity_on_hand: int = 0):
self.name = name
self.unit_price = unit_price
self.quantity_on_hand = quantity_on_hand
def total_cost(self) -> float:
return self.unit_price * self.quantity_on_hand
これがdataclassを使用すると下記の用にかける。
from dataclasses import dataclass
@dataclass
class InventoryItem:
"""Class for keeping track of an item in inventory."""
name: str
unit_price: float
quantity_on_hand: int = 0
def total_cost(self) -> float:
return self.unit_price * self.quantity_on_hand
コンストラクタの中でのアノテーションやデフォルト引数と
インスタンス変数と2回書かなくてよいし、アノテーションも見やすいと思います。
②型指定いないとエラーがでる
アノテーションをつけないと下記のエラーがでます。
残念ながらアノテーションなのでバリデーションチェックの機能はもっていないです。
NameError: name 'unit_price' is not defined
③特殊メソッドが定義される
- repr
- eq
-
__lt__()
,__le__()
,__gt__()
,__ge__()
dataclassデコレータの引数として `order=True```
from dataclasses import dataclass
@dataclass(order=True)
class InventoryItem:
"""Class for keeping track of an item in inventory."""
number1: int
number2: int
item1 = InventoryItem(10, 20)
item2 = InventoryItem(15, 15)
item1 > item2 # False
上記での比較はインスタンス変数のタプルを比較している状態となっています。
なので下記と同義です。
(10, 20) > (15, 15)
タプル同士の比較は第一引数同士の比較、
第一引数が同じであれば第二引数の比較、…
といった動きになります。
少し触って感じたメリットは以上です。
空辞書、空リストを用意する場合はfiled(default_factory)を使用
このようにデフォルト引数を指定してインスタンス使用しようとするとエラーがでてしまいます。
from dataclasses import dataclass
@dataclass()
class InventoryItem:
"""Class for keeping track of an item in inventory."""
data: dict = {}
item = InventoryItem()
エラー内容
ValueError: mutable default <class 'dict'> for field data is not allowed: use default_factory
デフォルト引数でNoneの指定はできるようですが、空辞書、空リストを用意する場合はエラーにも記載があるdefault_factoryを使用します。
from dataclasses import dataclass, field
@dataclass()
class InventoryItem:
"""Class for keeping track of an item in inventory."""
data1: dict = None
data2: dict = field(default_factory=dict)
data3: list = field(default_factory=list)
item = InventoryItem()
item # InventoryItem(data1=None, data2={}, data3=[])
dataclasses_json
インスタンス後にto_json, to_dictで辞書型でデータを取り出すことができます。
from dataclasses import dataclass, field
from dataclasses_json import dataclass_json
@dataclass_json # 必ずdataclass_jsonが上にくる必要がある
@dataclass
class InventoryItem:
"""Class for keeping track of an item in inventory."""
data1: dict = None
data2: dict = field(default_factory=dict)
data3: list = field(default_factory=list)
item = InventoryItem({'a': 1}, {'b': 3}, [1, 24])
item.to_json() # {"data1": {"a": 1}, "data2": {"b": 3}, "data3": [1, 24]}