Python字典是哈希表的一个例子吗?

Tom*_*ert 170 python hash dictionary hashtable hashmap

Python中的一个基本数据结构是字典,它允许用户记录"键"以查找任何类型的"值".这在内部实现为哈希表吗?如果没有,那是什么?

nos*_*klo 217

是的,它是一个哈希映射或哈希表.您可以阅读python的字典实现的描述,由Tim彼得斯书面,这里.

这就是为什么你不能使用'nothable'作为dict键的东西,比如列表:

>>> a = {}
>>> b = ['some', 'list']
>>> hash(b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list objects are unhashable
>>> a[b] = 'some'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list objects are unhashable
Run Code Online (Sandbox Code Playgroud)

您可以阅读有关哈希表的更多信息,检查它是如何在python中实现的,以及为什么以这种方式实现它.


Bob*_*ein 27

Python字典必须比hash()上的表查找更多.通过粗暴的实验,我发现了这个哈希冲突:

>>> hash(1.1)
2040142438
>>> hash(4504.1)
2040142438
Run Code Online (Sandbox Code Playgroud)

然而它并没有打破字典:

>>> d = { 1.1: 'a', 4504.1: 'b' }
>>> d[1.1]
'a'
>>> d[4504.1]
'b'
Run Code Online (Sandbox Code Playgroud)

完整性检查:

>>> for k,v in d.items(): print(hash(k))
2040142438
2040142438
Run Code Online (Sandbox Code Playgroud)

可能还有另一个超出hash()的查找级别,可以避免字典键之间的冲突.或者dict()可能使用不同的哈希.

(顺便说一句,这在Python 2.7.10中.与Python 3.4.3和3.5.0中的相同故事发生冲突hash(1.1) == hash(214748749.8).)

  • 所以碰撞是不可避免的.集合S可能包含无限大量的项目,您希望它散列到计算机可以存储的数字.哈希表的每个可用实现都解决了冲突,其中两种最常见的方法是a)开放寻址和b)链接.仅仅因为它没有使用完美的哈希并不意味着它不是哈希表. (11认同)
  • 它有碰撞的变通方法. (8认同)
  • @YanfengLiu我相信这些与TurnipEntropy提出的观点完全相同。 (3认同)
  • 冲突通常会发生,因为有无限可能的可哈希值和有限的哈希码。即使是哈希表也必须以某种方式处理冲突。 (2认同)
  • 在 Python 3.7 中,实际上看起来有 2E20 减 1 个可能的哈希值。从 -1E20 减 1 到 (+)1E20 减 1。试试 `hash('我像一朵云一样孤独地徘徊,飘荡在高高的山谷和山丘上,突然间,我看到一群人,一群金黄水仙花。')` 如果你有足够的兴趣,这给出了一个 19 位的十进制 - `-4037225020714749784`。继续用你自己的话,孩子们,哈希仍然是一个 19 位数字。我假设您可以在 Python 中散列的字符串长度有限制,但可以肯定地说可能的字符串比可能的值多得多。顺便说一下,`hash(False)` = 0。 (2认同)
  • 它不会破坏字典的原因是因为在幕后重复值是使用链接列表实现的,并且它们与返回到它们生成的键的指针一起存储。 (2认同)

Ben*_*ein 20

是.在内部,它实现为基于Z/2上的本原多项式的开放散列().


Jer*_*ell 7

扩展nosklo的解释:

a = {}
b = ['some', 'list']
a[b] = 'some' # this won't work
a[tuple(b)] = 'some' # this will, same as a['some', 'list']
Run Code Online (Sandbox Code Playgroud)