概観
質問が解決されました。ただし、この回答には、データクラスの基本的な理解に役立ついくつかの実用的な例が追加されています。
正確にpythonデータクラスとは何ですか、いつそれらを使用するのが最適ですか?
- コードジェネレーター:ボイラープレートコードを生成します。通常のクラスに特別なメソッドを実装するか、データクラスに自動的に実装させるかを選択できます。
- データコンテナ:構造物が多いような点線、属性アクセスのホールドデータ(例えばタプルとdicts)、そのクラス、
namedtuple
およびその他。
「デフォルトの変更可能な名前付きタプル[s]」
後者のフレーズの意味は次のとおりです。
- mutable:デフォルトでは、dataclass属性を再割り当てできます。オプションでそれらを不変にすることができます(以下の例を参照)。
- namedtuple:
namedtuple
または通常のクラスのように、ドットで区切られた属性アクセスがあります。
- default:デフォルト値を属性に割り当てることができます。
一般的なクラスと比較すると、主にボイラープレートコードを入力する手間が省けます。
特徴
これはデータクラス機能の概要です(TL; DR?次のセクションの概要表を参照)。
あなたが得るもの
以下は、データクラスからデフォルトで取得する機能です。
属性+表現+比較
import dataclasses
@dataclasses.dataclass
#@dataclasses.dataclass() # alternative
class Color:
r : int = 0
g : int = 0
b : int = 0
これらのデフォルトは、次のキーワードをに自動的に設定することで提供されますTrue
。
@dataclasses.dataclass(init=True, repr=True, eq=True)
何をオンにできるか
適切なキーワードがに設定されている場合、追加の機能を使用できますTrue
。
注文
@dataclasses.dataclass(order=True)
class Color:
r : int = 0
g : int = 0
b : int = 0
強い等価テストと< > <= >=
同様に、順序付けメソッドが実装されました(オーバーロード演算子functools.total_ordering
:)。
ハッシュ可能、可変
@dataclasses.dataclass(unsafe_hash=True) # override base `__hash__`
class Color:
...
オブジェクトは潜在的に変更可能(望ましくない可能性があります)ですが、ハッシュが実装されています。
ハッシュ可能、不変
@dataclasses.dataclass(frozen=True) # `eq=True` (default) to be immutable
class Color:
...
ハッシュが実装され、オブジェクトの変更または属性への割り当てが許可されなくなりました。
全体として、unsafe_hash=True
またはの場合、オブジェクトはハッシュ可能frozen=True
です。
詳細については、元のハッシュロジックテーブルも参照してください。
あなたが得ないもの
次の機能を使用するには、特別なメソッドを手動で実装する必要があります。
開梱
@dataclasses.dataclass
class Color:
r : int = 0
g : int = 0
b : int = 0
def __iter__(self):
yield from dataclasses.astuple(self)
最適化
@dataclasses.dataclass
class SlottedColor:
__slots__ = ["r", "b", "g"]
r : int
g : int
b : int
オブジェクトサイズが縮小されました。
>>> imp sys
>>> sys.getsizeof(Color)
1056
>>> sys.getsizeof(SlottedColor)
888
状況によっては、__slots__
インスタンスの作成と属性へのアクセスの速度も向上します。また、スロットはデフォルトの割り当てを許可しません。それ以外の場合は、ValueError
発生します。
このブログ投稿でスロットの詳細をご覧ください。
要約表
+----------------------+----------------------+----------------------------------------------------+-----------------------------------------+
| Feature | Keyword | Example | Implement in a Class |
+----------------------+----------------------+----------------------------------------------------+-----------------------------------------+
| Attributes | init | Color().r -> 0 | __init__ |
| Representation | repr | Color() -> Color(r=0, g=0, b=0) | __repr__ |
| Comparision* | eq | Color() == Color(0, 0, 0) -> True | __eq__ |
| | | | |
| Order | order | sorted([Color(0, 50, 0), Color()]) -> ... | __lt__, __le__, __gt__, __ge__ |
| Hashable | unsafe_hash/frozen | {Color(), {Color()}} -> {Color(r=0, g=0, b=0)} | __hash__ |
| Immutable | frozen + eq | Color().r = 10 -> TypeError | __setattr__, __delattr__ |
| | | | |
| Unpacking+ | - | r, g, b = Color() | __iter__ |
| Optimization+ | - | sys.getsizeof(SlottedColor) -> 888 | __slots__ |
+----------------------+----------------------+----------------------------------------------------+-----------------------------------------+
+これらのメソッドは自動的に生成されず、データクラスに手動で実装する必要があります。
* __ne__
は必要ないため、実装されていません。
追加機能
初期化後
@dataclasses.dataclass
class RGBA:
r : int = 0
g : int = 0
b : int = 0
a : float = 1.0
def __post_init__(self):
self.a : int = int(self.a * 255)
RGBA(127, 0, 255, 0.5)
# RGBA(r=127, g=0, b=255, a=127)
継承
@dataclasses.dataclass
class RGBA(Color):
a : int = 0
変換
データクラスをタプルまたは辞書に再帰的に変換します。
>>> dataclasses.astuple(Color(128, 0, 255))
(128, 0, 255)
>>> dataclasses.asdict(Color(128, 0, 255))
{r: 128, g: 0, b: 255}
制限事項
参考文献
- R.ヘッティンガーの話上のデータクラス:すべてのコードジェネレータを終了するコードジェネレータ
- T. Hunnerによる、より簡単なクラスに関する講演:Pythonクラスですべての問題を解消
- ハッシュの詳細に関するPythonのドキュメント
- Python 3.7のデータクラスに関する究極のガイドに関する本物のPython ガイド
- A. ShawのPython 3.7データクラスの概要ツアーに関するブログ投稿
- E.スミスのgithubのリポジトリ上のデータクラス
namedtuple
sは不変であり、属性のデフォルト値を持つことはできませんが、データクラスは変更可能であり、それらを持つことができます。