Python中的基本数据结构之一是字典,它允许记录“键”,用于查找任何类型的“值”。这在内部实现为哈希表吗?如果不是,是什么?
当前回答
Python字典中必须有比hash()上的表查找更多的内容。通过残酷的实验,我发现了这个哈希冲突:
>>> 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)处发生冲突。)
(我在Python 3.9.6中没有发现任何冲突。由于哈希值更大——hash(1.1) == 230584300921369601——我估计我的桌面需要一千年才能找到一个哈希值。我稍后再回答你。)
其他回答
是的。在内部,它被实现为基于Z/2(源)上的原始多项式的开放哈希。
Python字典中必须有比hash()上的表查找更多的内容。通过残酷的实验,我发现了这个哈希冲突:
>>> 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)处发生冲突。)
(我在Python 3.9.6中没有发现任何冲突。由于哈希值更大——hash(1.1) == 230584300921369601——我估计我的桌面需要一千年才能找到一个哈希值。我稍后再回答你。)
是的,它是一个哈希映射或哈希表。你可以在这里阅读Tim Peters所写的python dict实现的描述。
这就是为什么你不能使用“不可哈希”的东西作为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中实现的,以及为什么要这样实现。
扩展一下诺斯克洛的解释:
a = {}
b = ['some', 'list']
a[b] = 'some' # this won't work
a[tuple(b)] = 'some' # this will, same as a['some', 'list']
推荐文章
- 将Pandas或Numpy Nan替换为None以用于MysqlDB
- 使用pandas对同一列进行多个聚合
- 使用Python解析HTML
- django MultiValueDictKeyError错误,我如何处理它
- 如何在for循环期间修改列表条目?
- 我如何在Django中创建一个鼻涕虫?
- 没有名为'django.core.urlresolvers'的模块
- 蟒蛇导出环境文件
- Django - makemigrations -未检测到任何更改
- SQLAlchemy:引擎、连接和会话差异
- 在Python Pandas中删除多个列中的所有重复行
- 更改pandas DataFrame中的特定列名
- 将Pandas多索引转换为列
- 熊猫在每组中获得最高的n个记录
- 熊猫数据帧得到每组的第一行