Python字典是哈希表的示例吗?


187

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


2
如果您对技术细节感兴趣,则Beautiful代码中的一篇文章介绍了Python dict实现的内部。
Torsten Marek

那是《美丽代码》中我最喜欢的章节之一。
DGentry

4
这是布兰登·克雷格·罗兹(Brandon Craig Rhodes)的演讲,讨论python词典的工作原理,youtube.com / watch?v = C4Kc8xzcA68
坎多拉'17

我寻找了一段时间的表示字典的图,该图描述了内存和CPython中的实现。感谢您参考这本书!
Chen A.

Answers:


239

是的,它是一个哈希映射或哈希表。您可以在此处阅读由蒂姆·彼得斯(Tim Peters)编写的有关python 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

您可以阅读有关散列表的更多信息,查看它如何在python中实现以及为什么以这种方式实现


1
蒂姆·彼得斯(Tim Peters)的连接缝将被破坏,那里是否有干净的连接?
Matt Alcock 2012年

1
@MattAlcock:我已经更新了链接。有时(通常是由于某人希望删除其电子邮件地址),python列表档案被重建并且电子邮件的id发生更改,从而中断了这些链接。pydotorg管理员通常试图避免这种情况。
马丁·彼得斯

但是使用.keys()可以检索键列表。真正的哈希表不会存储键,而只是散列以节省空间。
noɥʇʎԀʎzɐɹƆ

有关python dict实施的更完整说明,请访问:laurentluce.com/posts/python-dictionary-implementation
Daniel Goldfarb

32

除了在hash()上进行表查找之外,Python词典还必须有更多内容。通过残酷的实验,我发现了这种哈希冲突

>>> hash(1.1)
2040142438
>>> hash(4504.1)
2040142438

但这并没有破坏字典:

>>> d = { 1.1: 'a', 4504.1: 'b' }
>>> d[1.1]
'a'
>>> d[4504.1]
'b'

完整性检查:

>>> for k,v in d.items(): print(hash(k))
2040142438
2040142438

可能除了hash()之外还有另一种查找级别,可以避免字典键之间的冲突。也许dict()使用不同的哈希值。

(顺便说一句,在python 2.7.10中是这样。在Python 3.4.3和3.5.0中是相同的,但在处发生了冲突hash(1.1) == hash(214748749.8)。)


14
因此,碰撞是不可避免的。集S可能包含无限多个项目,并且您希望它散列到计算机可以存储的数字。哈希表的每种可用实现都可以解决冲突,其中最常见的两种方法是a)开放式寻址和b)链接。仅仅因为它没有利用完美的哈希表并不意味着它不是哈希表。
TurnipEntropy

1
通常会发生冲突,因为存在无限可能的可哈希值和有限的哈希码。即使是哈希表也必须以某种方式处理冲突。
刘延峰

3
@YanfengLiu我相信这些与TurnipEntropy提出的观点完全相同。
鲍勃·斯坦

1
在Python 3.7中,实际上看起来好像有2E20减去1个可能的哈希值。从-1E20减1到(+)1E20减1。请尝试hash('I wandered lonely as a cloud, that drifts on high o\'er vales and hills, when all at once, I saw a crowd, a host of golden daffodils.')输入19位十进制数- -4037225020714749784如果您足够讨厌,就可以使用。继续,用孩子们自己的话说,哈希仍然是19位数字。我假设可以在Python中哈希的字符串的长度是有限制的,但是可以肯定地说比可能的值还多的字符串。且hash(False)= 0。
Will Croxford


7

为了扩展nosklo的解释:

a = {}
b = ['some', 'list']
a[b] = 'some' # this won't work
a[tuple(b)] = 'some' # this will, same as a['some', 'list']
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.