1

このページによると、 set.intersection__eq__メソッドを使用して要素の等価性をテストします。なぜこれが失敗するのか、誰かが私に説明できますか?

>>> Class Foo(object):
>>>     def __eq__(self, other):
>>>         return True
>>>
>>> set([Foo()]).intersection([Foo()])
set([])

2.7.3 を使用します。これを行う別の(過度に複雑ではない)方法はありますか?

4

1 に答える 1

5

上書きする__eq__場合は、常に も上書きする必要があります__hash__

「a == b の場合、ハッシュ (a) == ハッシュ (b) である必要があります。そうでない場合、セットと辞書は失敗します。」エリック

__hash__オブジェクトから整数を生成するために使用されます。これは、辞書のキーまたはセットの要素をバケットに入れるために使用され、それらをより速く見つけることができます。

を上書きしない場合__hash__、デフォルトのアルゴリズムでは、オブジェクトが同じであっても、異なるハッシュ整数が作成されます。

あなたの場合、私はこれを行います:

class Foo(object):
    def __eq__(self, other):
        return type(self) == type(other)
    def __hash__(self):
        return 1

クラスのすべてのオブジェクトは、そのクラスの他のすべてのオブジェクトと等しいため、それらはすべてセット内の同じバケット (1) にある必要があります。この方法でinも戻りますTrue

次のようになり__eq__ます。

  • Foo オブジェクトのみを比較する場合

    def __eq__(self, other):
        return self.number == other.number
    
  • Foo オブジェクトを他のオブジェクトとも比較する場合:

    def __eq__(self, other):
        return type(self) == type(other) and self.number == other.number
    
  • 等しいアルゴリズムが異なる異なるクラスがある場合は、double-dispatchをお勧めします。

    class Foo:
        def __eq__(self, other):
            return hasattr(other, '_equals_foo') and other._equals_foo(self)
        def _equals_foo(self, other):
            return self.number == other.number
        def _equals_bar(self, other):
            return False # Foo never equals Bar
    class Bar:
        def __eq__(self, other):
            return hasattr(other, '_equals_bar') and other._equals_bar(self)
        def _equals_foo(self, other):
            return False # Foo never equals Bar
        def _equals_bar(self, other):
            return True # Bar always equals Bar
    

    このようにして、abin の両方で、a == b等しい意味を決定します。

于 2013-07-14T17:10:53.383 に答える