Python设置交集和__eq__

时间:2013-07-14 17:04:39

标签: python python-2.7 set

根据this page,使用__eq__方法对元素相等性进行set.intersection测试。任何人都可以向我解释为什么会失败吗?

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

使用2.7.3。还有另一种(不是过于复杂)的方式吗?

1 个答案:

答案 0 :(得分:4)

如果您覆盖__eq__,也应始终覆盖__hash__

  

"如果a == b,则必须是hash(a)== hash(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
    

    这样,a中的ba == b决定了平等的含义。