7

subclass dictサブクラスのすべての辞書が不変になるようにPythonで実行したいと思います。

私の理解では、オブジェクトの同等性または同等性__hash__を意味するだけなので、不変性にどのように影響するのかわかりません。

だから、__hash__不変性を実装するために使用できますか?どのように ?

更新

目的は、APIからの一般的な応答をdictとして利用できることです。これは、グローバル変数として共有する必要があります。だから、それは何があっても無傷である必要がありますか?

4

4 に答える 4

9

私は公式の参照を見つけました:拒否されたPEPに含まれている提案。

class imdict(dict):
    def __hash__(self):
        return id(self)

    def _immutable(self, *args, **kws):
        raise TypeError('object is immutable')

    __setitem__ = _immutable
    __delitem__ = _immutable
    clear       = _immutable
    update      = _immutable
    setdefault  = _immutable
    pop         = _immutable
    popitem     = _immutable

アトリビューション:http ://www.python.org/dev/peps/pep-0351/

于 2012-06-14T04:42:00.510 に答える
6

だから、__hash__不変性を実装するために使用できますか?

いいえ、できません。__hash__オブジェクトは、そのメソッドが何をするかに関係なく、変更可能(または変更不可)にすることができます。

不変オブジェクトとの関係は__hash__、不変オブジェクトは変更できないため、によって返される値は__hash__構築後も一定のままであるということです。可変オブジェクトの場合、これが当てはまる場合と当てはまらない場合があります(推奨される方法は、そのようなオブジェクトが単にハッシュに失敗することです)。

詳細については、Issue 13707:hash()Constencyperiodを明確にするを参照してください。

于 2012-06-13T11:55:29.040 に答える
5

ハッシュ可能性と可変性の関係について:

有用であるためには、ハッシュ実装は次の特性を満たす必要があります。

  1. 等しいを使用して比較する2つのオブジェクトのハッシュ値は等しく==なければなりません。

  2. ハッシュ値は時間の経過とともに変化しない場合があります。

これらの2つのプロパティは、インスタンスを比較するときにハッシュ可能なクラスが可変プロパティを考慮に入れることができないことを意味し、インスタンスを比較するときに可変プロパティを考慮に入れるクラスはハッシュ可能ではないことを意味します。不変クラスは、比較に影響を与えることなくハッシュ可能にすることができます。

すべての組み込みの可変型はハッシュ可能ではなく、すべての不変の組み込み型はハッシュ可能です。これは主に上記の観察結果です。

ユーザー定義クラスは、デフォルトでオブジェクトIDに基づいて比較を定義しid()、ハッシュとして使用します。これらは変更可能ですが、インスタンスを比較するときに変更可能なデータは考慮されないため、ハッシュ可能にすることができます。

クラスをハッシュ可能にしても、魔法のように不変になるわけではありません。逆に、元の比較演算子を維持しながら辞書を合理的な方法でハッシュ可能にするには、最初に辞書を不変にする必要があります。

編集:あなたのアップデートに関して:

グローバルな不変辞書に相当するものを提供する方法はいくつかあります。

  1. collections.namedtuple()代わりにインスタンスを使用してください。

  2. 読み取り専用プロパティを持つユーザー定義クラスを使用します。

  3. 私は通常、次のようなものを使用します。

    _my_global_dict = {"a": 42, "b": 7}
    
    def request_value(key):
        return _my_global_dict[key]
    

    先頭の下線で、_my_global_dictアプリケーションコードに触れないようにする実装の詳細であることを明確にします。このコードでは、ディクショナリ値が変更可能なオブジェクトである場合でも、ディクショナリ値を変更できることに注意してください。この問題は、必要に応じて値のcopy.copy()sまたはsを返すことで解決できます。copy.deepcopy()

于 2012-06-13T12:34:43.563 に答える
1

凍結されたdictでは、ハッシュは拒否されたPEP416に従って単純に実装されます。

def __hash__(self):
    try:
        fs = frozenset(self.items())
    except TypeError:
        hash = -1
    else:
        hash = hash(fs)
    
    if hash == -1:
        raise TypeError("Not all values are hashable.")
    
    return hash

PS:私はパッケージの新しいメンテナーです。

于 2022-01-15T21:09:33.300 に答える