gpt4 book ai didi

python - 什么时候使用 hash() 调用 __eq__?

转载 作者:太空狗 更新时间:2023-10-29 22:14:57 24 4
gpt4 key购买 nike

如前所述here ,

下面的代码,

class Person(object):
def __init__(self, name, ssn, address):
self.name = name
self.ssn = ssn
self.address = address
def __hash__(self):
print('in hash')
return hash(self.ssn)
def __eq__(self, other):
print('in eq')
return self.ssn == other.ssn

bob = Person('bob', '1111-222-333', None)

jim = Person('jim bo', '1111-222-333', 'sf bay area')


dmv_appointments = {}
print('calling hash')
dmv_appointments[bob] = 'tomorrow'
print('calling hash')
print(dmv_appointments[jim])
print('calling hash again')
print(dmv_appointments[bob])

输出:

calling hash
in hash
calling hash
in hash
in eq
tomorrow
calling hash again
in hash
tomorrow

问题:

为什么 __eq__ 在访问 jim 而不是 bob 时被调用?

最佳答案

简答:字典查找首先在搜索存储桶时进行(廉价的)引用相等性检查(x is y),然后仅当失败时,才会进行(更昂贵的)相等性检查 (x == y)。

场景

__hash__ 函数不会在内部调用 __eq__。如果您构造了 bobjim,则不会调用此类方法。

接下来,您bob'tomorrow' 相关联。为了知道在字典的哪个桶中,您必须存储 bob,您计算哈希值。现在,一旦您完成了,我们就会存储 bob(以及正确存储桶中的值)。

接下来我们要获取jim。为了知道 jim 位于哪个存储桶中,我们计算哈希值。接下来我们开始在桶中搜索。该桶将包含 bob。我们首先执行引用检查(jim is bob)但失败了,因此我们回退到相等性检查。该检查成功,因此我们返回与 bob 对应的值:'tomorrow'

当我们要查找 bob 时,会发生相同的情况:我们计算哈希值,获取桶。对 bob is bob 执行reference check,结果成功。所以我们不需要(可能更昂贵的平等检查)。我们只需返回值 'tomorrow'

背景调查

先进行引用检查这一事实可以用以下(不健康的)代码证明:

class Person(object):
def __init__(self, name, ssn, address):
self.name = name
self.ssn = ssn
self.address = address
def __hash__(self):
print('in hash')
return hash(self.ssn)
<b>def __eq__(self, other):
print('in eq')
return False</b>

这里我们总是返回 False 来表示相等。所以即使:

>>> bob == bob
in eq
False
>>> bob is bob
True

bob 不等于它自己(这实际上不是好的设计,因为对于字典来说,它是一个对象等于它自己的契约:一个很好的相等关系自反对称传递)。然而,如果我们将 bob'tomorrow' 相关联,我们仍然能够获取与 bob 相关联的值:

>>> dmv_appointments = {}
>>> dmv_appointments[bob] = 'tomorrow'
in hash
>>> dmv_appointments[bob]
in hash
'tomorrow'

关于python - 什么时候使用 hash() 调用 __eq__?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44531020/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com