3
0

More than 1 year has passed since last update.

dataclassesの使い方

Last updated at Posted at 2022-07-04

公式サイトはこちら
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]}
3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0