Python 3.6+ 中的字典是有序的吗?

2024-11-18 08:41:00
admin
原创
272
摘要:问题描述:从 Python 3.6 开始,字典是按插入顺序排列的。它被描述为 CPython 实现细节,而不是语言功能。文档指出:dict()现在使用PyPy 首创的“紧凑”表示。与 Python 3.5 相比,新 dict() 的内存使用量减少了 20% 到 25%。PEP 468(在函数中保留 **kwa...

问题描述:

从 Python 3.6 开始,字典是按插入顺序排列的。它被描述为 CPython 实现细节,而不是语言功能。文档指出:

dict()现在使用PyPy 首创的“紧凑”表示。与 Python 3.5 相比,新 dict() 的内存使用量减少了 20% 到 25%。PEP 468(在函数中保留 **kwargs 的顺序。)由此实现。此新实现的保序方面被视为实现细节,不应依赖(这可能会在未来发生变化,但最好在更改语言规范以强制所有当前和未来的 Python 实现都使用保序语义之前,在语言的几个版本中拥有这个新的 dict 实现;这也有助于保持与旧版本的语言的向后兼容性,其中随机迭代顺序仍然有效,例如 Python 3.5)。(由 INADA Naoki 在问题 27350中贡献。想法最初由 Raymond Hettinger 提出。)

在保留元素顺序的同时,新字典实现如何比旧字典表现更好?


2017 年 12 月更新:Python 3.7保证dict保留插入顺序


解决方案 1:

Python 3.6+ 中的字典是有序的吗?

它们是按插入顺序排列的[1]

从 Python 3.6 开始,对于 Python 的 CPython 实现,字典会记住插入项的顺序这被视为 Python 3.6 中的实现细节OrderedDict;如果您希望在 Python 的其他实现(以及其他有序行为[1] )中保证插入顺序,则需要使用。

从 Python 3.7 开始,这是一个有保证的语言特性,而不仅仅是一个实现细节。来自 GvR 的 python-dev 消息:

就这样吧。“Dict 保持插入顺序”是裁决。谢谢!

这仅仅意味着你可以依赖它。如果其他 Python 实现希望成为符合 Python 3.7 的实现,它们也必须提供插入有序字典。


Python字典实现在保留元素顺序的同时,如何做到比旧字典3.6表现更好[2] ?

本质上,通过保留两个数组

  • 第一个数组按照插入顺序保存字典中的dk_entries条目(类型)。保持顺序的方法是,这是一个仅追加数组,新条目始终插入到末尾(插入顺序)。 PyDictKeyEntry

  • 第二个数组dk_indices保存数组的索引dk_entries(即,指示 中相应条目位置的值dk_entries)。此数组充当哈希表。对某个键进行哈希处理后,它会指向 中存储的索引之一dk_indices,并通过索引 来获取相应的条目dk_entries。由于只保留索引,因此此数组的类型取决于字典的整体大小(范围从类型int8_t1字节)到int32_t/ int64_t4/8字节)32/64位构建)

在之前的实现中,必须分配一个类型PyDictKeyEntry和大小的稀疏数组;不幸的是,这也导致了大量空白空间,因为出于性能原因,dk_size该数组不允许过满2/3 * dk_size。(并且空白空间仍然有大小!)。PyDictKeyEntry

现在情况不同了,因为只存储了所需的条目(已插入的条目),并且保留了类型为 s full的稀疏数组intX_tX取决于字典大小) 。空白空间从类型更改为。2/3 * dk_size`PyDictKeyEntry`intX_t

因此,显然,创建 类型的稀疏数组PyDictKeyEntry比用于存储 s 的稀疏数组需要更多的内存int

如果有兴趣的话,你可以在 Python-Dev 上看到有关此功能的完整对话,这是一篇值得一读的文章。


在 Raymond Hettinger 最初提出的提案中,可以看到所使用的数据结构的可视化,这抓住了该想法的主旨。

例如字典:

d = {'timmy': 'red', 'barry': 'green', 'guido': 'blue'}

目前存储为[keyhash,key,value]:

entries = [['--', '--', '--'],
           [-8522787127447073495, 'barry', 'green'],
           ['--', '--', '--'],
           ['--', '--', '--'],
           ['--', '--', '--'],
           [-9092791511155847987, 'timmy', 'red'],
           ['--', '--', '--'],
           [-6480567542315338377, 'guido', 'blue']]

相反,数据应按如下方式组织:

indices =  [None, 1, None, None, None, 0, None, 2]
entries =  [[-9092791511155847987, 'timmy', 'red'],
            [-8522787127447073495, 'barry', 'green'],
            [-6480567542315338377, 'guido', 'blue']]

正如您现在可以直观地看到的,在原始提案中,很多空间基本上是空的,以减少冲突并加快查找速度。使用新方法,您可以通过将稀疏性移动到索引中真正需要的地方来减少所需的内存。


[1]:我说的是“插入有序”而不是“有序”,因为在 OrderedDict 存在的情况下,“有序”暗示了 dict 对象不提供的进一步行为。OrderedDicts 是可逆的,提供顺序敏感的方法,并且主要提供顺序敏感的相等性测试(==!=)。dict 目前不提供任何这些行为/方法。


[2]:新字典实现的设计更紧凑,因此在内存方面表现更好;这是主要优点。速度方面,差异并不大,新字典可能会在某些地方引入轻微的回归(例如键查找),而在其他地方(想到迭代和调整大小)应该会提高性能。
总体而言,由于引入了紧凑性,字典的性能(尤其是在实际情况下)得到了改善。

解决方案 2:

以下是对原来第一个问题的回答:

我应该在 Python 3.6 中使用dict或吗?OrderedDict

我认为文档中的这句话实际上足以回答你的问题

此新实现的保序方面被视为实现细节,不应依赖

dict并不是明确地意味着是一个有序集合,所以如果你想保持一致并且不依赖新实现的副作用,你应该坚持使用OrderedDict

让你的代码适应未来:)

这里有一个关于此的争论。

编辑:Python 3.7 将保留此功能, 请参阅

解决方案 3:

更新:Guido van Rossum在邮件列表中宣布,从 Python 3.7 开始dict,所有 Python 实现都必须保留插入顺序。

解决方案 4:

我想参与上述讨论,但没有资格发表评论。

Python 3.8reversed()在字典中包含了该函数(从中删除了另一个差异)OrderedDict

现在可以使用 reversed() 以反向插入顺序对 dict 和 dictviews 进行迭代。(由 Rémi Lapeyre 在 bpo-33462 中贡献。)
查看 python 3.8 中的新功能

我没有看到任何提及相等运算符或其他特征,OrderedDict所以它们仍然不完全相同。

解决方案 5:

为了在 2020 年全面回答这个问题,让我引用Python 官方文档中的几句话:

在 3.7 版中更改:保证字典顺序与插入顺序一致。此行为是从 3.6 版开始的 CPython 实现细节。

在 3.7 版更改: 保证字典顺序与插入顺序一致。

在 3.8 版更改: 字典现在是可逆的。

字典和字典视图是可逆的。

关于OrderedDict与Dict的声明:

有序字典与普通字典类似,但具有一些与排序操作相关的额外功能。现在,内置 dict 类具有记住插入顺序的功能(这一新行为在 Python 3.7 中得到保证),它们变得不那么重要了。

解决方案 6:

在 3.7 版中更改:保证字典顺序与插入顺序一致。此行为是从 3.6 版开始的 CPython 实现细节。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2579  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1553  
  IPD(Integrated Product Development)流程作为一种先进的产品开发管理模式,在众多企业中得到了广泛应用。其中,技术评审与决策评审是IPD流程中至关重要的环节,它们既有明显的区别,又存在紧密的协同关系。深入理解这两者的区别与协同,对于企业有效实施IPD流程,提升产品开发效率与质量具有重要意义...
IPD管理流程   27  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、ClickUp、Freshdesk、GanttPRO、Planview、Smartsheet、Asana、Nifty、HubPlanner、Teamwork。在当今快速变化的商业环境中,项目管理软件已成为企业提升效率、优化资源分配和确保项目按时交付的关键工具。然而...
项目管理系统   22  
  建设工程项目质量关乎社会公众的生命财产安全,也影响着企业的声誉和可持续发展。高质量的建设工程不仅能为使用者提供舒适、安全的环境,还能提升城市形象,推动经济的健康发展。在实际的项目操作中,诸多因素会对工程质量产生影响,从规划设计到施工建设,再到后期的验收维护,每一个环节都至关重要。因此,探寻并运用有效的方法来提升建设工程...
工程项目管理制度   19  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用