[解決済み] データクラスとtyping.NamedTupleの主な使用例
疑問点
長い話
PEP-557
は Python 標準ライブラリにデータクラスを導入し、基本的には
collections.namedtuple
と
typing.NamedTuple
. そして今、私はnamedtupleがまだ良い解決策であるユースケースをどのように分けるかについて考えています。
NamedTupleに対するデータクラスの優位性
もちろん、すべての功績は
dataclass
が必要であれば
- ミュータブルオブジェクト
- 継承のサポート
-
property
デコレータ、管理可能な属性 - 箱から出してすぐに使えるメソッド定義、またはカスタマイズ可能なメソッド定義
データクラスの利点は、同じ PEP で簡単に説明されています。 なぜnamedtupleを使用しないのか .
Q: どのような場合にnamedtupleの方が良いのでしょうか?
しかし、namedtupleに対する反対の質問はどうでしょうか:なぜdataclassを使用しないのでしょうか? おそらくパフォーマンスの観点からnamedtupleの方が優れているのでしょうが、それについての確認はまだありません。
例
次のような状況を考えてみましょう。
静的に定義されたフィールド、タイプヒンティング、名前付きアクセスを持つ小さなコンテナにページの次元を保存するつもりです。さらなるハッシュ化、比較などは必要ありません。
NamedTupleのアプローチ。
from typing import NamedTuple
PageDimensions = NamedTuple("PageDimensions", [('width', int), ('height', int)])
DataClassのアプローチ。
from dataclasses import dataclass
@dataclass
class PageDimensions:
width: int
height: int
どの解決策が望ましいか、またその理由は?
追伸:この質問は、重複していませんが あれ というのは、ここでは ケース についてではなく、namedtupleの方が良い場合について尋ねているのです。 その違い (聞く前にドキュメントとソースをチェックしました)
どのように解決するのですか?
それはあなたのニーズによって異なります。それぞれに利点があります。
PyCon 2018でのDataclassesの解説はこちらです。 Raymond Hettinger - Dataclasses: すべてのコードジェネレータを終わらせるコードジェネレータ
この記事では
Dataclass
の実装はすべてPythonで書かれています。
であるのに対し
NamedTuple
では、これらの動作はすべて無償で提供されます。
NamedTuple
から継承しているからです。
tuple
. また
tuple
構造はCで書かれているので
標準的なメソッドは
NamedTuple
(ハッシュ、比較など)の方が速いです。
また、以下のことに注意してください。
Dataclass
は
dict
一方
NamedTuple
は
tuple
. このように、これらの構造を使うことにはメリットとデメリットがあるのです。例えば、スペース使用量は
NamedTuple
の方がスペースが少なくて済みますが、時間アクセスは
Dataclass
.
どうぞ、私の実験をご覧ください。
In [33]: a = PageDimensionsDC(width=10, height=10)
In [34]: sys.getsizeof(a) + sys.getsizeof(vars(a))
Out[34]: 168
In [35]: %timeit a.width
43.2 ns ± 1.05 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [36]: a = PageDimensionsNT(width=10, height=10)
In [37]: sys.getsizeof(a)
Out[37]: 64
In [38]: %timeit a.width
63.6 ns ± 1.33 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
の属性数を増やすと
NamedTuple
のアクセス時間は同じように短いままです。なぜなら、それぞれの属性に対して、属性の名前を持つプロパティが作成されるからです。例えば、私たちのケースでは、新しいクラスの名前空間の部分は次のようになります。
from operator import itemgetter
class_namespace = {
...
'width': property(itemgetter(0, doc="Alias for field number 0")),
'height': property(itemgetter(0, doc="Alias for field number 1"))**
}
どのような場合にnamedtupleがまだ良い選択なのでしょうか?
データ構造が必要なとき/できるとき
immutable, hashable, iterable, unpackable, comparable であることが必要な場合、次のようにします。
NamedTuple
. もし、何か
より複雑なもの、例えば継承の可能性などが必要な場合
を使用します。
Dataclass
.
関連
-
[解決済み] どうすれば、文字列中のリテラルな中抜き文字を印刷し、また.formatを使用することができるのでしょうか?
-
[解決済み] Pythonのクラスはなぜオブジェクトを継承するのですか?
-
[解決済み] JSONデータをファイルに書き込むにはどうしたらいいですか?
-
[解決済み] virtualenvで異なるバージョンのPythonを使用する
-
[解決済み] Pythonの "with "文は何のために作られたのですか?
-
[解決済み】なぜPythonはこのJSONデータをパースできないのですか?[終了] PythonがこのJSONデータをパースできないのはなぜですか?
-
[解決済み】データクラスとは何ですか、一般的なクラスとどう違うのですか?
-
[解決済み] Pythonです。未束縛のメソッドを束縛する?
-
[解決済み] Flask でグローバル変数はスレッドセーフか?リクエスト間でデータを共有するには?
-
[解決済み] pipの依存性/必要条件をリストアップする方法はありますか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】pythonの複数の戻り値を無視する
-
[解決済み】データクラスとは何ですか、一般的なクラスとどう違うのですか?
-
[解決済み] Django のテストデータベースをメモリ上だけで動作させるには?
-
[解決済み] Python 3でバイナリデータを標準出力に書き込むには?
-
[解決済み] 文字列から先頭と末尾のスペースを削除するには?
-
[解決済み] Django 1.7で初期マイグレーションからマイグレートバックする方法は?
-
[解決済み] pandasのタイムゾーンに対応したDateTimeIndexを、特定のタイムゾーンに対応したナイーブなタイムスタンプに変換する。
-
[解決済み] Flaskで非同期タスクを作る
-
[解決済み] Pythonで、ウェブサイトが404か200かを確認するためにurllibをどのように使用しますか?
-
[解決済み] Pythonでリストが空かどうかをチェックする方法は?重複