1. ホーム
  2. python

[解決済み] Pythonic way to convert a dictionary into namedtuple or another hashable dict-like?

2023-04-18 14:42:14

質問

このような辞書があります。

d = {'a': 1, 'b': 2, 'c': 3, 'd': 4}

で、これを名前付きタプルに変換したいと思います。 私の現在のアプローチは、次のコードです。

namedTupleConstructor = namedtuple('myNamedTuple', ' '.join(sorted(d.keys())))
nt= namedTupleConstructor(**d)

を生成します。

myNamedTuple(a=1, b=2, c=3, d=4)

これは私のためにうまく動作する(と思う)、しかし、私は次のような組み込みが不足しています...

nt = namedtuple.from_dict() ?

UPDATE: コメントで議論されたように、私の辞書を名前付きタプルに変換したい理由は、ハッシュ化できるようにするためですが、まだ一般的にdictのように使うことができます。

UPDATE2: 私がこの質問を投稿してから4年が経ちました。 TLK が新しい回答を投稿しています。 は、データクラスデコレータを使用することを推奨しており、これは本当に素晴らしいと思います。これは本当に素晴らしいことだと思います。私は、今後これを使用することになると思います。

どのように解決するのですか?

サブクラスを作成するには、dictのキーを直接渡せばよいでしょう。

MyTuple = namedtuple('MyTuple', d)

このdict、または一致するキーを持つ他のdictからタプルのインスタンスを作成するようになりました。

my_tuple = MyTuple(**d)

注意してください。 名前付きタプルの比較対象は の値のみを比較します。 (順序付き)で比較します。これらは、通常のタプルをそのまま置き換えるように設計されており、追加機能として名前付き属性へのアクセスがあります。 フィールド名は等価比較の際に考慮されません。 . それは、あなたが望んでいたものでも、期待したものでもないかもしれません。 namedtuple タイプとは異なります。これは dict 等価比較とは異なり、キーを考慮し、順序に関係なく比較します。

である型を本当に必要としない読者のために。 タプルのサブクラスである である型を本当に必要としない読者にとっては、そもそもnamedtupleを使う意味はあまりないでしょう。もし、フィールドに属性アクセス構文を使いたいだけなら、よりシンプルで簡単な方法で 名前空間 オブジェクトを作成する方がシンプルで簡単でしょう。

>>> from types import SimpleNamespace
>>> SimpleNamespace(**d)
namespace(a=1, b=2, c=3, d=4)

私の辞書を名前付きタプルに変換したい理由は、ハッシュ化できるようにするためですが、それでも一般的にはディクショナリのように使用することができます。

レシピのようなハッシュ可能な "attrdict"については、凍結させたものをチェックしてみてください。 ボックス :

>>> from box import Box
>>> b = Box(d, frozen_box=True)
>>> hash(b)
7686694140185755210
>>> b.a
1
>>> b["a"]
1
>>> b["a"] = 2
BoxError: Box is frozen

また、Pythonの後のバージョンでは、凍結されたマッピングタイプが登場する可能性があります。

PEP 603 -- コレクションへのfrozenmap型の追加