Python如何';实现了哪些内置词典?
有人知道python的内置字典类型是如何实现的吗?我的理解是,这是某种哈希表,但我还没有找到任何明确的答案。Python字典使用() NB开放寻址,又称封闭哈希,正如维基百科中所指出的,不应与它的相反的开放哈希混淆Python如何';实现了哪些内置词典?,python,data-structures,dictionary,Python,Data Structures,Dictionary,有人知道python的内置字典类型是如何实现的吗?我的理解是,这是某种哈希表,但我还没有找到任何明确的答案。Python字典使用() NB开放寻址,又称封闭哈希,正如维基百科中所指出的,不应与它的相反的开放哈希混淆 开放寻址意味着dict使用数组槽,当一个对象的主要位置在dict中时,使用“扰动”方案在同一数组中的不同索引处寻找对象的位置,其中对象的散列值起作用。以下是我能够组合的Python dict的全部内容(可能比任何人想知道的都多;但答案是全面的) Python字典实现为哈希表 哈希
开放寻址意味着dict使用数组槽,当一个对象的主要位置在dict中时,使用“扰动”方案在同一数组中的不同索引处寻找对象的位置,其中对象的散列值起作用。以下是我能够组合的Python dict的全部内容(可能比任何人想知道的都多;但答案是全面的)
- Python字典实现为哈希表
- 哈希表必须允许哈希冲突,即即使两个不同的键具有相同的哈希值,该表的实现也必须具有明确插入和检索键和值对的策略
- Python
使用开放寻址来解决哈希冲突(如下所述)(请参阅)dict
- Python哈希表只是一个连续的内存块(有点像数组,所以可以通过索引执行
lookup)O(1)
- 表中的每个插槽只能存储一个条目。这很重要
- 表中的每个条目实际上是三个值的组合:
。这是作为C结构实现的(请参阅) - 下图是Python哈希表的逻辑表示。在下图中,左侧的
是哈希表中插槽的索引(它们仅用于说明目的,显然不随表一起存储!) Python哈希表的逻辑模型 -+-----------------+ 0| | -+-----------------+ 1| ... | -+-----------------+ .| ... | -+-----------------+ 我| -+-----------------+ .| ... | -+-----------------+ n || -+-----------------+0,1,…,i,…
- 当一个新的dict初始化时,它从8个插槽开始。(请参阅)
- 在向表中添加条目时,我们从某个插槽开始,
,该插槽基于键的哈希值。CPython最初使用i
(其中i=hash(key)&mask
,但这并不重要)。只需注意,检查的初始插槽mask=PyDictMINSIZE-1
,取决于密钥的哈希值i
- 如果该插槽为空,则该条目将添加到插槽中(我的意思是,条目)。但如果该插槽已被占用怎么办?很可能是因为另一个条目具有相同的哈希(哈希冲突!)
- 如果插槽被占用,CPython(甚至是PyPy)将插槽中条目的哈希和键与要插入的当前条目的哈希和键进行比较()分别。如果两者都匹配,则认为该条目已经存在,放弃并移动到下一个要插入的条目。如果哈希或键不匹配,则开始探测
- 探测仅仅意味着它逐槽搜索插槽以找到一个空插槽。从技术上讲,我们可以一个接一个地,
,然后使用第一个可用的插槽(这是线性探测)。但由于注释中详细解释的原因(请参阅),CPython使用随机探测。在随机探测中,以伪随机顺序拾取下一个插槽。条目添加到第一个空插槽中。对于本讨论,用于拾取下一个插槽的实际算法并不十分重要(有关探测算法,请参阅)。重要的是要探测插槽,直到找到第一个空插槽i+1,i+2,
- 查找也会发生同样的情况,只从初始插槽i开始(其中i取决于密钥的哈希值)。如果哈希值和密钥都与插槽中的条目不匹配,它将开始探测,直到找到匹配的插槽。如果所有插槽都已用完,它将报告失败
- 顺便说一句,
如果已满三分之二,则将调整其大小。这样可以避免减慢查找速度。(请参阅)dict
- 它们是散列表(参见下面的Python实现细节)
- 一个新的布局和算法,如Python3.6,使它们
- 按键插入排序,以及
- 占用更少的空间
- 在性能上几乎没有成本
- 另一个优化在dict共享密钥时节省空间(在特殊情况下)
<hash> <key> <value>
...010001 ffeb678c 633241c4
... ... ...
对于64位机器,每增加一个字典,每个键最多可以节省16个字节
自定义对象和备选方案的共享键
<hash> <key> <value>
null null null
...010001 ffeb678c 633241c4 # addresses of the keys and values
null null null
... ... ...
[null, 0, null, null, null, null, null, null]
<hash> <key> <value>
...010001 ffeb678c 633241c4
... ... ...
hash key dict_0 dict_1 dict_2...
...010001 ffeb678c 633241c4 fffad420 ...
... ... ... ... ...