__hash__
返回给定对象的值。但是,出于好奇,如果不是,会发生什么呢?这会导致什么样的破坏?
class BadIdea(object):
def __hash__(self):
return random.randint(0, 10000)
我知道
__contains__
__getitem__
和
o
会表现得奇怪,因此,命令和场景会奇怪。您可能最终会在dict/set中以“孤儿”值。
还会发生什么?它会崩溃口译员还是损坏的内部结构?
divent的斑点,因此找不到对象。这就是为什么dict Keys应该始终不变的原因。
这里是一个很小的例子:假设我们将o
o
的初始哈希是3。牌表: 0 1 2 3 4 5 6 7 +----+---+---+---+ - +---+---+ - + - +---+ | | | | O | | | | | +----+---+---+---+ - +---+---+ - + - +---+ ^ 我们将O放在这里,因为它是3
现在,假设更改为
6
的哈希。如果我们想从dict中检索
o
,我们会看地点
6
,但是那里什么都没有!在查询数据结构时,这将导致假阴性。实际上,在dict的情况下,上面数组的每个元素都可能具有与之相关的“值”,并且一个位置可能会有多个元素(例如,ahashcollision)。另外,我们通常会在决定放置元素的位置时,将哈希值模量的大小为数组的大小。但是,不管所有这些细节如何,上面的示例仍然准确地传达出当对象的哈希代码更改时可能出了什么问题。
它会崩溃解释器,还是损坏的内部结构?没有,这不会发生。当我们说一个物体的哈希变化是“危险的”时,我们的意思是危险的,因为它本质上会破坏哈希的目的,并使代码很难甚至不可能推理。我们并不是说可能会导致坠机事件的意义。
当您惹上Hashing在Github上有一篇很棒的文章:
时会发生什么。 首先,您需要知道Python的期望(在文章中引用):
对象的哈希不会在对象的寿命上发生变化(换句话说,悬空对象应该是不可变的)。
a == b
hash(a) == hash(b)
>>> class Bad(object):
... def __init__(self, arg):
... self.arg = arg
... def __hash__(self):
... return hash(self.arg)
...
>>> Bad(1)
<__main__.Bad object at ...>
>>> hash(Bad(1))
1
>>> a = Bad(1)
>>> b = {a:1}
>>> a.arg = 2
>>> hash(a)
2
>>> b[a]
Traceback (most recent call last):
...
KeyError: <__main__.Bad object at ...>
在这里,我们通过突变用于计算哈希的A的论点来隐式更改A的哈希。结果,该对象不再在字典中找到,该字典使用哈希查找对象。
__setattr__
升起
AttributeError
,但是即使到那时,我也可以通过修改对象的
__dict__
来强制更改它。这就是我们说Python是一种“同意成年人”语言时的含义。它不会使python崩溃
,但意外的行为将在dict/set和基于对象哈希的所有事物中发生。