当前位置: 首页 > 知识库问答 >
问题:

词典在Python3.6+中订购吗?

申屠秦斩
2023-03-14

dict()现在使用了Pypy首创的“紧凑”表示形式。与Python3.5相比,新的dict()的内存使用量减少了20%到25%。PEP 468(保留函数中**kwargs的顺序。)是通过这个来实现的。这个新实现的保序方面被认为是一个实现细节,不应该被依赖(这在将来可能会改变,但是在更改语言规范以强制所有当前和将来的Python实现的保序语义之前,希望在几个版本中使用这个新的dict实现;这也有助于保持与仍然有效的随机迭代顺序的语言旧版本的向后兼容性,例如Python 3.5)。(INADA Naoki供稿于第27350期。最初由Raymond Hettinger提出。)

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

共有1个答案

温浩大
2023-03-14

词典在Python3.6+中订购吗?

它们是插入有序的[1]。从Python3.6开始,对于Python的CPython实现,字典记住插入项的顺序。这被认为是Python3.6中的一个实现细节;如果希望在Python的其他实现(和其他有序行为[1])中保证插入顺序,则需要使用ordereddict

从Python3.7开始,这不再是一个实现细节,而是成为一种语言特性。从gvr的python-dev消息中:

>

  • 第一个数组dk_entries按照插入的顺序保存字典的条目(类型为pyDictKeyentries)。保持顺序是通过这是一个仅追加数组来实现的,其中新项总是插入在末尾(插入顺序)。

    第二个是dk_index,它保存dk_entries数组的索引(即指示相应条目在dk_entries中的位置的值)。这个数组充当哈希表。当一个键被散列时,它会导致存储在dk_index中的索引之一,并通过索引dk_entries来获取相应的条目。由于只保留索引,此数组的类型取决于字典的总体大小(范围从类型int8_t(1字节)到int32_t/int64_t(4/8字节)的32/64位构建)

    在前面的实现中,必须分配类型pydictkeyentry和大小dk_size的稀疏数组;不幸的是,由于性能原因,该数组不允许超过2/3*dk_sizefull。(空的空间仍然有pydictkeyentrysize!)。

    现在情况并非如此,因为只存储了必需的条目(那些已经插入的条目),并且保留了intx_t类型的稀疏数组(x取决于dict大小)2/3*dk_sizes full。空格从类型pyhtml" target="_blank">dictkeyentry更改为intx_t

    因此,显然,创建pydictkeyentry类型的稀疏数组比存储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']]
    

  •  类似资料:
    • 问题内容: 与以前的版本不同,字典在Python 3.6中排序(至少在CPython实现下)。这似乎是一个重大更改,但只是文档中的一小段。它被描述为CPython实现细节而不是语言功能,但这也意味着将来可能会成为标准。 在保留元素顺序的同时,新的词典实现如何比旧的实现更好? 以下是文档中的文字: 现在使用PyPy率先提出的“compact”表示形式。与Python 3.5相比,新dict()的内存

    • 我想按字母顺序排列字符串“s”的子串,长度为“k” 我尝试首先使用函数对字符串的字符进行词法排序,然后尝试打印第一个和最后一个子字符串 预期输出:将字典上最小和最大的子字符串作为单个换行符分隔的字符串返回。

    • 问题内容: 我目前有使用PIVOT生成如下表的查询: 我想做的是,但看起来像是拉伸,结果是值递减。 这是查询: 这样做会产生错误,因此可以指定列吗? 问题答案: 试试这个:

    • 我是ElasticSearch的新手,我目前正在尝试编写一个涉及聚合的ElasticSearch查询,它将为我获取涉及某些字段的前5个桶(查询中涉及的字段数量是动态的,它可以在2个字段和5个字段之间的任何位置)。 我面临的问题是,团队当前的ElasticSearch版本不支持多术语,因此我恢复了复合聚合,将top_hits作为子聚合器,这样我就可以获得前5个桶。然而,我没有根据doc_count/

    • 问题内容: 我有一个与数据库对话的servlet,然后返回一个有序(按时间排序)对象的列表。在servlet部分,我有 从日志中,我可以看到数据库以正确的顺序返回了User对象。 在前端,我有 但是顺序改变了。 我只在返回的列表很大(超过130个用户)时才注意到这一点。 我尝试使用Firebug进行调试,Firebug中的“响应选项卡”显示列表的顺序与servlet中的日志不同。 我做错了什么吗?

    • 我是Flink的新手,我试图理解Flink是如何在其的并行抽象中命令调用。考虑这个产生部分和的流的例子: 我希望它的输出是流:。事实上,就在这里。 是否可以安全地假设这种情况始终存在,尤其是在从具有大量并行性的源读取数据时?