Python set()和__hash__混淆

时间:2013-06-17 11:20:13

标签: python hash set

我定义的一个类在set()中用于过滤掉相等的对象。但它没有像我期望的那样起作用,所以我显然明白了一些错误。

class Foo(object):

    def __hash__(self):
        return 7

x = set()
x.add(Foo())
assert len(x) == 1
x.add(Foo())
assert len(x) == 1    # AssertionError

我希望该集合只包含一个元素,但它有两个元素。那是为什么?

1 个答案:

答案 0 :(得分:6)

知道哈希冲突发生在集合(哈希映射)中,没有哈希算法足以为每个项目提供唯一的哈希值,否则需要很长时间才能计算出来。当发生碰撞时,python会回退到使用__eq__检查值的相等性,以确保它们不相同。

class Foo(object):

    def __hash__(self):
        return 7
    def __eq__(self, other):
        return True

>>> x = set()
>>> x.add(Foo())
>>> assert len(x) == 1
>>> x.add(Foo())
>>> assert len(x) == 1
>>> 

这就是为什么你看到可怕的运行时超过here的原因,但请注意,即使它们有O(N)最坏情况(一切都是哈希冲突),你可以期待O(1)摊销的成员资格检查。 )。由于Python的智能实现,最糟糕的情况非常不太可能发生。