2016-06-29 17 views
5

私は、Python辞書がキーを見つけるために内部でやっていなければならないことを理解しようとしています。 ハッシュが最初に評価され、衝突がある場合、eqがTrueを返すものを見つけるまで、Pythonはキーを繰り返し処理します。これは次のコードは動作しますなぜ私は(唯一の内部を理解するためのテストコード)思ってしまう:Python dictの__hash__と__eq__評価の順序は何ですか?

class MyClass(object): 
    def __eq__(self, other): 
     return False 

    def __hash__(self): 
     return 42 

if __name__=='__main__': 

    o1 = MyClass() 
    o2 = MyClass() 
    d = {o1: 'o1', o2: 'o2'} 
    assert(o1 in d)  # 1 
    assert(d[o1]=='o1') # 2 
    assert(o2 in d)  # 3 
    assert(d[o2]=='o2') # 4 

辞書は正しい鍵を見つけることができませんでしべきではありません(両方で「O1」または「O2」のいずれかを返しますケース#2と#4、または内部実装に応じてエラーをスローする)。どのようにして正しいキーに着陸することができますか?(eqはFalseを返すので、キーを正しく '照合'できないようにする必要があります)。

私はハッシングで見てきたすべてのドキュメントは常にハッシュ私はこれらの2は、この中で役割を果たしているだけのものだと思います一緒にEQ、決してCMPNEなどを、言及しますシナリオ。

答えて

5

dictキーとして使用するものはすべて、bool(x == x) is Trueという不変式を満たす必要があります。 (私はちょうどx == xと言っていただろうが、それはブール値でもない合理的なオブジェクトがある)

dictはこれが保持されると仮定しているので、キーの等価性をチェックするルーチンは、 ==を使用する前にこの予備チェックは実装の詳細です。起こっているのか起こっていないのかに頼るべきではありません。

(x == x) is not Trueにはfloat('nan')numpy.array([1, 2])が含まれています。

+0

この例では、o1 == o1はFalseを返しますが、id(o1)== id(o1)はTrueを返しますか? –

+0

私はそれを試しましたが、o1 == o1はFalseを返し、id(o1)== id(o1)はTrueを返します。 –

+0

@TimurRidjanovic:はい。 'is'はオブジェクトの同一性を比較するより安全で時にはより効率的な方法です。 – user2357112