我有一个名为GraphEdge
的类,我希望在一个集(内置的set
类型)中通过其tail
和{__init__
设置。在
如果不定义__hash__
,则会看到以下行为:
>>> E = GraphEdge('A', 'B')
>>> H = GraphEdge('A', 'B')
>>> hash(E)
139731804758160
>>> hash(H)
139731804760784
>>> S = set()
>>> S.add(E)
>>> S.add(H)
>>> S
set([('A', 'B'), ('A', 'B')])
集合无法知道E
和{GraphEdge
定义了一个相当幼稚的哈希函数,如下所示:
现在,上述工作如预期:
>>> E = GraphEdge('A', 'B')
>>> H = GraphEdge('A', 'B')
>>> hash(E)
409150083
>>> hash(H)
409150083
>>> S = set()
>>> S.add(E)
>>> S.add(H)
>>> S
set([('A', 'B')])
但是很明显,在本例中,('A', 'B')
和{('B', 'A')
添加到已经包含('A', 'B')
的集合中。但事实并非如此:
>>> E = GraphEdge('A', 'B')
>>> H = GraphEdge('B', 'A')
>>> hash(E)
409150083
>>> hash(H)
409150083
>>> S = set()
>>> S.add(E)
>>> S.add(H)
>>> S
set([('A', 'B'), ('B', 'A')])
那么set类型是否使用哈希?如果是这样,最后一种情况如何可能?如果不是,为什么第一个场景(没有__hash__
定义)不起作用?我错过什么了吗?在
编辑:为了供将来的读者参考,我已经定义了__eq__
(也基于tail
和head
)。在
你有一个哈希冲突。在哈希冲突中,集合使用==运算符检查它们是否真正相等。在
如果至少需要一个},则应该始终同时定义它们。如果两个对象的哈希值相等,则执行额外的
__eq__()
和{__eq__()
检查以验证唯一性。在理解hash和==是如何一起工作的很重要,因为这两者都是由集合使用的。对于两个值x和y,重要的规则是:
(x等于y意味着x和y的散列相等)。但是,反之亦然:两个不相等的值可以有相同的哈希值。在
集合(和dicts)将使用哈希来获得相等的近似值,但将使用实数相等运算来判断两个值是否相同。在
相关问题 更多 >
编程相关推荐