Python 如何使用_散列的返回值?
假设我编写了一个类,但没有为它定义一个Python 如何使用_散列的返回值?,python,hash,key,Python,Hash,Key,假设我编写了一个类,但没有为它定义一个\uuuuuuuuuuuuuuuuuuuuuuuuuuuu。然后根据,默认值为id(self)(self)的内存地址 但是,我在文档中没有看到该值是如何使用的。 因此,如果我的\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。但是,这并不意味着\uuuuu hash\uuuu的
\uuuuuuuuuuuuuuuuuuuuuuuuuuuu
。然后根据,默认值为id(self)
(self
)的内存地址
但是,我在文档中没有看到该值是如何使用的。因此,如果我的
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。但是,这并不意味着\uuuuu hash\uuuu
的返回值被用作此基础哈希表中bin元素的键。
实际上,我的问题是:\uuuuuuhash\uuuuuu
返回的值会发生什么变化?它是直接用作密钥,还是其哈希(或对其执行的其他计算的结果)用作哈希表的密钥
如果有关系的话,我会用python2.7
编辑:澄清一下,我不是问如何处理哈希冲突。在python中。相反,我要问的是\uuuuu hash\uuuu
的返回值如何转换为相应存储桶的内存地址(?)。当一个对象存储在字典中时,使用\uuuuu hash\uuu
来确定该对象所在的原始存储箱。然而,这并不意味着字典中的一个对象会与另一个对象混淆——它们仍然会检查对象是否相等。这只是意味着字典对该类型的对象进行散列时会比其他类型的对象慢一些。当然,从逻辑上(从使用散列表的代码的角度来看),对象本身就是键。如果在哈希表中搜索键“foo”
,则无论哈希表中的其他对象与“foo”
具有相同的哈希值,只有当哈希表中存储的其中一个键值对的键等于“foo”
时,才会返回相应的值
我不知道Python到底做什么,但哈希表实现必须考虑哈希冲突。如果哈希表数组具有N
插槽,则如果插入N+1
值(并且该表未首先调整大小),则必须存在冲突。另外,正如您提到的\uuuuuu hash\uuuuu
总是返回1的情况一样,或者正如hash函数实现的一个怪癖,可能有两个对象具有完全相同的hash代码
有两种主要策略用于处理内存中单个计算机的哈希表中的哈希冲突(用于分布式哈希表等的不同技术):
数组中的每个插槽都是一个列表(通常是一个链表),散列到k
模N
的所有值都放在插槽k
的列表中。因此,如果散列值发生冲突,这不是问题,因为具有相同散列值的两个对象最终都位于同一个列表中
某种探测计划。基本上,如果要插入的对象的散列值等于k
模N
,则可以查看插槽k
。如果已满,则将一些公式应用于当前位置(可能只需添加1),然后查看下一个插槽。给定原始哈希值和到目前为止的探测数,按照常规模式选择下一个插槽,并继续探测,直到找到打开的插槽。这是较少使用的,因为如果您对实现不小心,您可能会遇到集群问题,即在找到对象之前必须进行多次探测
Wikipedia更多地讨论了哈希表的实现。因为Python的哈希表的大小是二的幂,哈希值的低位决定了哈希表中的位置(或者至少是初始探测的位置)
表大小为n的探针序列如下所示:
def gen_probes(hashvalue, n):
'Same sequence of probes used in the current dictionary design'
mask = n - 1
PERTURB_SHIFT = 5
if hashvalue < 0:
hashvalue = -hashvalue
i = hashvalue & mask
yield i
perturb = hashvalue
while True:
i = (5 * i + perturb + 1) & 0xFFFFFFFFFFFFFFFF
yield i & mask
perturb >>= PERTURB_SHIFT
存储为大小为8的数组,每个条目的格式为(散列、键、值)
:
Python字典中的键插入C源代码可以在这里找到:可能与@BrenBarn重复:这不是该问题的重复。这个问题问散列是如何工作的,以及为什么在一个集合中不复制等价的对象。我的问题是\uuuuu hash\uuuuu
的输出如何转换为存储该对象的存储桶的内存位置?我不认为这是由该语言定义的,因为Python的大多数方面都不是在该粒度级别定义的。正如我链接到的帖子(以及其他提到的帖子)中所描述的,行为已经定义好了。而且,我不太明白你所说的“底层哈希表”是什么意思。什么是底层哈希表,底层是什么<代码>\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
仅在散列对象时使用(例如,在字典或集合中使用)。如果您从未以需要散列的方式使用对象,那么它的\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
做什么都无关紧要。@BrenBarn:底层散列bucket(我假设它是在C
中实现的,即Python字典的底层是一个散列表(它有bucket),在C中实现。散列用于确定原始bin
@inspectorG4dget:“我知道有严格的一对一”
-不,不完全是。不同的对象可以映射到同一个bin-当这种情况发生时,Python字典会处理冲突。老实问,如果这是真的,为什么{true:'a',1:'b'}
求值为{True:'b'}
?(True
和1
都是散列到1
)@BrianMarshall:很好的发现!看起来这是因为True==1
-这意味着哈希表正在测试相等性而不是身份。两个对象可以返回相同的散列值,但彼此之间仍然不能=
。(演示:classobj2(object):pass;Obj2.\uuuuuhash\uuuuuu=lambda s:1;print hash(Obj2())==hash(Obj2());print Obj2()==Obj2()
。lambda
位只允许我在
d = {'timmy': 'red', 'barry': 'green', 'guido': 'blue'}
entries = [['--', '--', '--'],
[-8522787127447073495, 'barry', 'green'],
['--', '--', '--'],
['--', '--', '--'],
['--', '--', '--'],
[-9092791511155847987, 'timmy', 'red'],
['--', '--', '--'],
[-6480567542315338377, 'guido', 'blue']]