Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python如何';实现了哪些内置词典?_Python_Data Structures_Dictionary - Fatal编程技术网

Python如何';实现了哪些内置词典?

Python如何';实现了哪些内置词典?,python,data-structures,dictionary,Python,Data Structures,Dictionary,有人知道python的内置字典类型是如何实现的吗?我的理解是,这是某种哈希表,但我还没有找到任何明确的答案。Python字典使用() NB开放寻址,又称封闭哈希,正如维基百科中所指出的,不应与它的相反的开放哈希混淆 开放寻址意味着dict使用数组槽,当一个对象的主要位置在dict中时,使用“扰动”方案在同一数组中的不同索引处寻找对象的位置,其中对象的散列值起作用。以下是我能够组合的Python dict的全部内容(可能比任何人想知道的都多;但答案是全面的) Python字典实现为哈希表 哈希

有人知道python的内置字典类型是如何实现的吗?我的理解是,这是某种哈希表,但我还没有找到任何明确的答案。

Python字典使用()

NB开放寻址,又称封闭哈希,正如维基百科中所指出的,不应与它的相反的开放哈希混淆


开放寻址意味着dict使用数组槽,当一个对象的主要位置在dict中时,使用“扰动”方案在同一数组中的不同索引处寻找对象的位置,其中对象的散列值起作用。

以下是我能够组合的Python dict的全部内容(可能比任何人想知道的都多;但答案是全面的)

  • Python字典实现为哈希表

  • 哈希表必须允许哈希冲突,即即使两个不同的键具有相同的哈希值,该表的实现也必须具有明确插入和检索键和值对的策略

  • Python
    dict
    使用开放寻址来解决哈希冲突(如下所述)(请参阅)

  • Python哈希表只是一个连续的内存块(有点像数组,所以可以通过索引执行
    O(1)
    lookup)

  • 表中的每个插槽只能存储一个条目。这很重要

  • 表中的每个条目实际上是三个值的组合:。这是作为C结构实现的(请参阅)

  • 下图是Python哈希表的逻辑表示。在下图中,左侧的
    0,1,…,i,…
    是哈希表中插槽的索引(它们仅用于说明目的,显然不随表一起存储!)

    Python哈希表的逻辑模型 -+-----------------+ 0| | -+-----------------+ 1| ... | -+-----------------+ .| ... | -+-----------------+ 我| -+-----------------+ .| ... | -+-----------------+ n || -+-----------------+
  • 当一个新的dict初始化时,它从8个插槽开始。(请参阅)

  • 在向表中添加条目时,我们从某个插槽开始,
    i
    ,该插槽基于键的哈希值。CPython最初使用
    i=hash(key)&mask
    (其中
    mask=PyDictMINSIZE-1
    ,但这并不重要)。只需注意,检查的初始插槽
    i
    ,取决于密钥的哈希值

  • 如果该插槽为空,则该条目将添加到插槽中(我的意思是,条目)。但如果该插槽已被占用怎么办?很可能是因为另一个条目具有相同的哈希(哈希冲突!)

  • 如果插槽被占用,CPython(甚至是PyPy)将插槽中条目的哈希和键与要插入的当前条目的哈希和键进行比较()分别。如果两者都匹配,则认为该条目已经存在,放弃并移动到下一个要插入的条目。如果哈希或键不匹配,则开始探测

  • 探测仅仅意味着它逐槽搜索插槽以找到一个空插槽。从技术上讲,我们可以一个接一个地,
    i+1,i+2,
    ,然后使用第一个可用的插槽(这是线性探测)。但由于注释中详细解释的原因(请参阅),CPython使用随机探测。在随机探测中,以伪随机顺序拾取下一个插槽。条目添加到第一个空插槽中。对于本讨论,用于拾取下一个插槽的实际算法并不十分重要(有关探测算法,请参阅)。重要的是要探测插槽,直到找到第一个空插槽

  • 查找也会发生同样的情况,只从初始插槽i开始(其中i取决于密钥的哈希值)。如果哈希值和密钥都与插槽中的条目不匹配,它将开始探测,直到找到匹配的插槽。如果所有插槽都已用完,它将报告失败

  • 顺便说一句,
    dict
    如果已满三分之二,则将调整其大小。这样可以避免减慢查找速度。(请参阅)

注意:我做了关于Python Dict实现的研究,以回应我自己关于Dict中的多个条目如何具有相同的哈希值的问题。我在这里发布了一个稍加编辑的回复版本,因为所有的研究都与这个问题非常相关

Python的内置字典是如何实现的

以下是简短的课程:

  • 它们是散列表(参见下面的Python实现细节)
  • 一个新的布局和算法,如Python3.6,使它们
    • 按键插入排序,以及
    • 占用更少的空间
    • 在性能上几乎没有成本
  • 另一个优化在dict共享密钥时节省空间(在特殊情况下)
有序方面在Python3.6中是非官方的(以便让其他实现有机会跟上),但是

Python的字典是哈希表 很长一段时间,它的工作方式与此完全相同。Python会预先分配8个空行,并使用哈希来确定将键值对粘贴到何处。例如,如果键值的哈希以001结尾,它会将其粘贴到1(即第2个)索引中(如下面的示例)

我们的表只是按照插入顺序填充:

   <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  ...
      ...         ...    ...       ...       ...