1. ホーム
  2. python

[解決済み] フローズン・ディクト」とは、どのようなものでしょうか?

2022-04-14 09:02:53

質問

  • フローズンセットは、フローズンセットです。
  • フリーズしたリストはタプルになる可能性があります。
  • フローズンディクトはどうなるのでしょうか?不変でハッシュ可能なディクショナリーです。

のようなものでしょうかね。 collections.namedtuple しかし、それはむしろfrozen-keys dict(半分凍ったdict)のようなものです。そうでしょう?

フローズンディクショナリーは、次のようなものでなければなりません。 keys , values , get などに対応し in , for など。

を更新しました。

* そこにあるのは: https://www.python.org/dev/peps/pep-0603

解決方法は?

Pythonには組み込みのfrozendict型がありません。これはあまり頻繁には使えないことがわかりました(それでも、おそらく frozenset です)。

このような型を必要とする最も一般的な理由は、未知の引数を持つ関数の呼び出しをメモするときです。dict のハッシュ可能な等価値 (値がハッシュ可能) を保存するための最も一般的な解決策は、次のようなものです。 tuple(sorted(kwargs.iteritems())) .

これは、ソートが少々非常識でないかによります。Pythonはここでソートが合理的な結果をもたらすことを積極的に約束することはできません。(しかし、他のことはあまり約束できないので、あまり気にしないでください。)


Dictのように動作するラッパーを簡単に作ることができます。それは次のようなものです。

import collections

class FrozenDict(collections.Mapping):
    """Don't forget the docstrings!!"""

    def __init__(self, *args, **kwargs):
        self._d = dict(*args, **kwargs)
        self._hash = None

    def __iter__(self):
        return iter(self._d)

    def __len__(self):
        return len(self._d)

    def __getitem__(self, key):
        return self._d[key]

    def __hash__(self):
        # It would have been simpler and maybe more obvious to 
        # use hash(tuple(sorted(self._d.iteritems()))) from this discussion
        # so far, but this solution is O(n). I don't know what kind of 
        # n we are going to run into, but sometimes it's hard to resist the 
        # urge to optimize when it will gain improved algorithmic performance.
        if self._hash is None:
            hash_ = 0
            for pair in self.items():
                hash_ ^= hash(pair)
            self._hash = hash_
        return self._hash

素晴らしい出来栄えのはずです。

>>> x = FrozenDict(a=1, b=2)
>>> y = FrozenDict(a=1, b=2)
>>> x is y
False
>>> x == y
True
>>> x == {'a': 1, 'b': 2}
True
>>> d = {x: 'foo'}
>>> d[y]
'foo'