当前位置: 首页 > 面试题库 >

如何实现Python的内置词典?

诸正谊
2023-03-14
问题内容

有谁知道python内置字典类型是如何实现的?我的理解是,这是某种哈希表,但我无法找到任何确定的答案。


问题答案:

这是我能够汇总的有关Python字典的所有内容(可能比任何人都想知道的要多;但是答案很全面)。

  • Python字典实现为哈希表。
  • 哈希表必须允许哈希冲突,即,即使两个不同的键具有相同的哈希值,该表的实现也必须具有明确插入和检索键和值对的策略。
  • Python dict使用开放式寻址解决哈希冲突(如下所述)(请参阅dictobject.c:296-297)。
  • Python哈希表只是一个连续的内存块(有点像一个数组,因此您可以O(1)按索引进行查找)。
  • 表中的每个插槽只能存储一个条目。这个很重要。
  • 表中的每个条目实际上是三个值的组合:<hash,key,value>。这是作为C结构实现的(请参阅dictobject.h:51-56)。
  • 下图是Python哈希表的逻辑表示。在下图中,0, 1, ..., i, ...左侧是哈希表中插槽的索引(它们仅用于说明目的,与表显然没有一起存储!)。
# Logical model of Python Hash table
-+-----------------+
0| <hash|key|value>|
-+-----------------+
1|      ...        |
-+-----------------+
.|      ...        |
-+-----------------+
i|      ...        |
-+-----------------+
.|      ...        |
-+-----------------+
n|      ...        |
-+-----------------+
  • 初始化新字典时,它将以8 个插槽开始。(见dictobject.h:49)
  • 在向表中添加条目时,我们从某个槽开始i,该槽基于键的哈希值。CPython最初使用i = hash(key) & mask(where mask = PyDictMINSIZE - 1,但这并不重要)。请注意,i选中的初始插槽取决于密钥的哈希值。
  • 如果该插槽为空,则将条目添加到该插槽(通过输入,我的意思是<hash|key|value>)。但是,如果那个插槽被占用了呢?最可能是因为另一个条目具有相同的哈希(哈希冲突!)
  • 如果插槽被占用,CPython的(甚至PyPy)比较哈希和密钥(通过比较我的意思是==比较不is比较)在对哈希和当前项目的关键插槽的条目要插入(dictobject.c :337,344-345)。如果两者都匹配,则认为该条目已存在,放弃并继续下一个要插入的条目。如果哈希或密钥不匹配,它将开始探测。
  • 探测只是意味着它逐个插槽搜索插槽以找到一个空插槽。从技术上讲,我们可以一个接一个地i+1, i+2, …使用,然后使用第一个可用的(线性探测)。但是由于注释中详细解释的原因(请参阅dictobject.c:33-126),CPython使用了随机探测。在随机探测中,以伪随机顺序拾取下一个时隙。该条目将添加到第一个空插槽。对于此讨论,用于选择下一个时隙的实际算法并不十分重要(有关探测的算法,请参见dictobject.c:33-126)。重要的是对插槽进行探测,直到找到第一个空插槽为止。
  • 查找也会发生相同的情况,只是从初始插槽i(其中i取决于键的哈希值)开始。如果哈希和密钥都与插槽中的条目不匹配,则它将开始探测,直到找到具有匹配项的插槽。如果所有插槽均已耗尽,则报告失败。
  • 顺便说一句,dict如果三分之二已满,将调整大小。这样可以避免减慢查找速度。(参见dictobject.h:64-65)

注意:我对Python Dict的实现进行了研究,以回答我自己的问题,即字典中的多个条目如何具有相同的哈希值。我在此处发布了对此回复的略作修改的版本,因为所有的研究也都与此问题相关。



 类似资料:
  • 问题内容: 我试图做到这一点,这样我的站点上的mp3可以通过单击鼠标左键来下载,而不必单击鼠标右键并另存为。因此,为此,我必须设置Content- Disposition:附件。这是我的第一个网站,所以我不知道如何实际执行此操作,但是我是在html标记中执行此操作还是在托管网站上以某种方式进行设置? 这是我的标记外观的示例。 问题答案: MP3列表示例: download.php:

  • 4.3 内置的 Resource 实现 spring 直接提供了多种开箱即用的 Resource 实现。 4.3.1 UrlResource UrlResource 封装了一个 java.net.URL 对象,用来访问 URL 可以正常访问的任意对象,比如文件、an HTTP target, an FTP target, 等等。所有的 URL 都可以用一个标准化的字符串来表示。如通过正确的标准化前

  • 问题内容: 我想知道python字典如何在后台运行,尤其是动态方面?创建字典时,其初始大小是多少?如果我们用很多元素更新它,我想我们需要扩大哈希表。我想我们需要重新计算散列函数以适应新的更大的散列表的大小,同时又与先前的散列表保持某种逻辑? 如您所见,我不完全了解此结构的内部。 问题答案: (部分)以下答案来自“ 升级Python技能”:检查字典。有关Python哈希表的更多信息,请参见The H

  • 本文向大家介绍python如何实现内容写在图片上,包括了python如何实现内容写在图片上的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了python将内容写在图片上的具体代码,供大家参考,具体内容如下 效果图 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。

  • 问题内容: 我见过有人说python 中的对象具有O(1)成员资格检查。如何在内部实现它们以允许这样做?它使用哪种数据结构?该实现还有什么其他含义? 这里的每个答案都非常有启发性,但是我只能接受一个答案,因此,我将选择与原始问题最接近的答案。谢谢你的信息! 问题答案: 实际上,CPython的集合被实现为类似于带有伪值的字典(键是集合的成员)的字典,并且进行了一些优化,可以利用这种缺乏值的方式 因

  • 问题内容: 我的班级有一个字典,例如: 然后,我想在MyClass实例中使用字典的键来访问字典,例如: 我知道这应该由__getattr__实现,但是我是Python的新手,我并不完全知道如何实现它。 问题答案: 不过在实施时要小心,您将需要进行一些修改: 如果您不需要设置属性,只需使用namedtuple例如。 如果您想要默认参数,则可以围绕它编写包装类: 或者作为函数看起来更好: