オブジェクトが を実装している場合、__hash__()
特定の Python オブジェクトのストックを作成する一般的かつ迅速な方法は、 です。しかし、これは効率的ですか?this SO answerによると、オブジェクトの属性のタプルのハッシュは「適切」ですが、Python にとって最も効率的かどうかを示しているようには見えません。それとも、 for each オブジェクトを実装し、このページの実際のハッシュ アルゴリズムを使用して、個々の属性の値を によって返される最終的な値に混ぜ合わせた 方がよいでしょうか?return hash(str(self))
__str__()
__hash__()
__hash__()
この SO questionから Jenkins ハッシュ ルーチンを実装したふりをします。どちら__hash__()
を使うのが良いでしょうか?:
# hash str(self)
def __hash__(self):
return hash(str(self))
# hash of tuple of attributes
def __hash__(self):
return hash((self.attr1, self.attr2, self.attr3,
self.attr4, self.attr5, self.attr6))
# jenkins hash
def __hash__(self):
from jenkins import mix, final
a = self.attr1
b = self.attr2
c = self.attr3
a, b, c = mix(a, b, c)
a += self.attr4
b += self.attr5
c += self.attr6
a, b, c = final(a, b, c)
return c
簡単にするために、サンプル オブジェクトの属性はすべて整数であると仮定します。また、すべてのオブジェクトが基底クラスから派生し、各オブジェクトが独自の を実装していると仮定します__str__()
。最初のハッシュを使用する場合のトレードオフは、それを基本クラスにも実装でき、各派生オブジェクトに追加のコードを追加しないことです。しかし、2 番目または 3 番目の__hash__()
実装が何らかの点で優れている場合、各派生オブジェクトに追加されたコードのコストが相殺されるでしょうか (それぞれが異なる属性を持つ可能性があるため)。
編集:import
3 番目の実装にあるの__hash__()
は、サンプル モジュール + オブジェクト全体を下書きしたくなかったからです。import
関数の呼び出しごとではなく、モジュールの先頭で実際に発生すると仮定します。
結論:このクローズド SO questionに対する回答とコメントによると、速度や効率のためではなく、 と の根底にある二重性__hash__
のために、タプル ハッシュの実装が本当に必要なようです__eq__
。ハッシュ値の範囲は何らかの形式 (たとえば、32 ビットまたは 64 ビット) に制限されるため、ハッシュ衝突が発生した場合は、オブジェクトの等価性がチェックされます。したがって、__eq__()
自己/他者の属性のタプル比較を使用してオブジェクトごとに実装__hash__()
するので、物事のハッシュ/等価性を尊重するために、属性タプルを使用して実装したいと考えています。