6

自分のカスタムクラス(dictから派生)のオブジェクトから別のカスタムクラスのオブジェクトへのマッピングを作成する必要があります。私が見ているように、これを行うには2つの方法があります。

  1. オブジェクトをハッシュ可能にすることができます。これをどうやってやるのかわかりません。実装できることはわかっています__hash__()が、実際にハッシュ(整数である必要があります)を計算する方法がわかりません。

  2. オブジェクトを比較できるので、リスト[(myobj、myotherobj)]を作成してから、タプルの最初の項目がルックアップキーと同じであるタプルを見つけるルックアップを実装できます。これを実装するのは簡単です(オブジェクトの数が少ない)が、このようなものが標準ライブラリにすでに存在する場合は、車輪の再発明を避けたいと思います。

ハッシュできないものを調べたいというのはよくある問題のように思われるので、誰かがすでにこの問題を解決していると思います。__hash()__dictのようなオブジェクトを実装する方法や、ハッシュ不可能なルックアップテーブルを作成する他の標準的な方法があるかどうかについての提案はありますか?

4

4 に答える 4

3

キーとして可変オブジェクトを使用したマッピングは、一般的に困難です。それは本当にあなたが望むものですか?オブジェクトが不変であると考える場合(Pythonで不変性を実際に強制する方法はありません)、またはオブジェクトがマッピングでキーとして使用されている間は変更されないことがわかっている場合は、オブジェクトに独自のハッシュ関数を実装できます。いくつかの方法。たとえば、オブジェクトにハッシュ可能なデータメンバーしかない場合は、すべてのデータメンバーのタプルのハッシュをオブジェクトハッシュとして返すことができます。

オブジェクトがdictに似ている場合は、すべてのKey-Valueペアの凍結セットのハッシュを使用できます。

def __hash__(self):
    return hash(frozenset(self.iteritems()))

これは、すべての値がハッシュ可能である場合にのみ機能します。ハッシュの再計算(すべてのルックアップで実行される)を保存するために、ハッシュ値をキャッシュし、ダーティフラグが設定されている場合はそれを再計算することができます。

于 2010-12-16T15:16:35.387 に答える
2

簡単な解決策は、lookup[id(myobj)] = myotherobjの代わりに行うことのようですlookup[myobj] = myotherobj。このアプローチについて何かコメントはありますか?

于 2010-12-16T15:38:40.893 に答える
1

カスタムクラスに追加のハッシュ不可能なオブジェクトを格納していない場合は、次のように機能するはずです。

def __hash__(self):
    return hash(self.items())
于 2010-12-16T15:11:36.633 に答える
1

これは、 http: //code.activestate.com/recipes/414283/frozendictから取得したの実装です。

class frozendict(dict):
    def _blocked_attribute(obj):
        raise AttributeError, "A frozendict cannot be modified."
    _blocked_attribute = property(_blocked_attribute)

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

    def __new__(cls, *args):
        new = dict.__new__(cls)
        dict.__init__(new, *args)
        return new

    def __init__(self, *args):
        pass

    def __hash__(self):
        try:
            return self._cached_hash
        except AttributeError:
            h = self._cached_hash = hash(tuple(sorted(self.items())))
            return h

    def __repr__(self):
        return "frozendict(%s)" % dict.__repr__(self)

Spacecowboyの回答のtuple(sorted(self.items()))ようfrozenset(self.iteritems())に置き換えます。そして、クラスに追加することを検討してください。__slots__ = ("_cached_hash",)

于 2010-12-16T15:35:42.643 に答える