我写了这个简单的代码,我试图了解究竟发生了什么。我创建了相等的对象,只将其中一个放在字典中。
然后,使用第二个对象作为键,我尝试打印其值的name属性。
由于我的哈希函数,字典返回与我插入的密钥对应的哈希值,对于obj1和obj2是相同的。
这是我的问题:我的哈希函数检查两个对象是否确实相等或者是碰撞的情况吗?
我希望问题很明确。
class Test:
def __init__(self, name):
self.name = name
def __eq__(self, other):
return (isinstance(other, type(self)) and self.name == other.name)
def __hash__(self):
return hash(self.name)
obj1 = Test('abc')
obj2 = Test('abc')
d = {}
d[obj1] = obj1
print(d[obj2].name)
答案 0 :(得分:0)
您可以通过测试几种组合轻松解决这个问题。请考虑以下两种类型:
class AlwaysEqualConstantHash:
def __eq__(self, other):
print('AlwaysEqualConstantHash eq')
return True
def __hash__(self):
print('AlwaysEqualConstantHash hash')
return 4
class NeverEqualConstantHash:
def __eq__(self, other):
print('NeverEqualConstantHash eq')
return False
def __hash__(self):
print('NeverEqualConstantHash hash')
return 4
现在让我们把它放在字典中,看看会发生什么:
>>> d = {}
>>> d[AlwaysEqualConstantHash()] = 'a'
AlwaysEqualConstantHash hash
>>> d[AlwaysEqualConstantHash()]
AlwaysEqualConstantHash hash
AlwaysEqualConstantHash eq
'a'
>>> d[AlwaysEqualConstantHash()] = 'b'
AlwaysEqualConstantHash hash
AlwaysEqualConstantHash eq
>>> d
{<__main__.AlwaysEqualConstantHash object at 0x00000083E8174A90>: 'b'}
如您所见,哈希一直用于处理字典中的元素。一旦在字典中存在具有相同散列的元素,则还进行相等比较以判断现有元素是否等于新元素。因此,由于我们所有新的AlwaysEqualConstantHash
对象都与另一个对象相同,所以它们都可以用作字典中的相同键。
>>> d = {}
>>> d[NeverEqualConstantHash()] = 'a'
NeverEqualConstantHash hash
>>> d[NeverEqualConstantHash()]
NeverEqualConstantHash hash
NeverEqualConstantHash eq
Traceback (most recent call last):
File "<pyshell#56>", line 1, in <module>
d[NeverEqualConstantHash()]
KeyError: <__main__.NeverEqualConstantHash object at 0x00000083E8186BA8>
>>> d[NeverEqualConstantHash()] = 'b'
NeverEqualConstantHash hash
NeverEqualConstantHash eq
>>> d
{<__main__.NeverEqualConstantHash object at 0x00000083E8186F60>: 'a', <__main__.NeverEqualConstantHash object at 0x00000083E8186FD0>: 'b'}
对于NeverEqualConstantHash
,这是非常不同的。哈希也一直在使用,但由于新对象永远不会与另一个对象相等,我们无法以这种方式检索现有对象。
>>> x = NeverEqualConstantHash()
>>> d[x] = 'foo'
NeverEqualConstantHash hash
NeverEqualConstantHash eq
NeverEqualConstantHash eq
>>> d[x]
NeverEqualConstantHash hash
NeverEqualConstantHash eq
NeverEqualConstantHash eq
'foo'
如果我们使用完全相同的键,我们仍然可以检索该元素,因为它不需要使用__eq__
与自身进行比较。我们还看到如何为具有相同散列的每个现有元素调用__eq__
,以便检查这个新对象是否与另一个相等。
所以是的,哈希用于快速将元素排序到字典中。对于被认为相等的元素,哈希必须相等。仅对于与现有元素的哈希冲突,__eq__
用于确保两个对象都引用相同的元素。