python - zfill用法 - str i.zfill 6




是否在Python 3.6+中订购了字典? (3)

字典在Python 3.6中排序(至少在CPython实现下),与之前的版本不同。 这似乎是一个重大变化,但它只是 documentation 的一小段。 它被描述为CPython实现细节而不是语言特性,但也暗示这可能成为未来的标准。

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

以下是文档中的文字:

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

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


是否在Python 3.6+中订购了字典?

它们是 有序插入的 [1] 。 从Python 3.6开始,对于Python的CPython实现,字典 记住了插入项的顺序 这被认为是Python 3.6中的实现细节 ; 如果你想要在其他Python实现(和其他有序行为 [1] )中 保证 插入排序,你需要使用 OrderedDict

从Python 3.7开始 ,这不再是一个实现细节,而是成为一种语言功能。 guaranteed

这样做。 “Dict保持插入秩序”是裁决。 谢谢!

这只是意味着 你可以依赖它 。 Python的其他实现还必须提供插入有序字典,如果他们希望成为Python 3.7的一致性实现。

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

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

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

  • 第二个, dk_indices ,保存 dk_entries 数组的索引(即,指示 dk_entries 相应条目的位置的值)。 此数组充当哈希表。 当对密钥进行散列时,它会导致存储在 dk_indices 中的索引之一,并通过索引 dk_entries 来获取相应的条目。 由于只保留索引,因此该数组的类型取决于字典的整体大小(范围从 int8_t 1 字节)到 int32_t / int64_t int8_t 字节) 64 位构建)

在前面的实现中,必须分配 PyDictKeyEntry 和size dk_size 类型的稀疏数组; 不幸的是,由于 性能原因 ,该阵列不允许超过 2/3 * dk_size ,因此它也导致了大量的空白空间。 (并且空白区域 仍然 具有 PyDictKeyEntry 大小!)。

现在情况并非如此,因为只存储了 所需的 条目(已插入的条目)和类型为 intX_t 的稀疏数组( X 取决于字典大小) 2/3 * dk_size s full保留。 空格从 PyDictKeyEntry 类型 PyDictKeyEntryintX_t

因此,显然,创建一个 PyDictKeyEntry 类型的稀疏数组要比用于存储 int 的稀疏数组要多得多。

如果感兴趣,你可以 mail.python.org/pipermail/python-dev/2016-September/146327.html 看到有关此功能的完整对话,这是一个很好的阅读。

在Raymond Hettinger提出的原始提案中 ,可以看到所使用的数据结构的可视化,其中捕获了该想法的要点。

例如,字典:

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

目前存储为:

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,“ordered”表示 dict 对象 不提供的 进一步行为。 OrderedDicts是可逆的,提供顺序敏感的方法,主要提供顺序敏感的相等测试( ==!= )。 dict 目前不提供任何这些行为/方法。

[2]:新的字典实现通过更紧凑的设计实现更好的 内存 ; 这是主要的好处。 速度方面,差异并不是那么激烈,新的字典可能会引入轻微的回归( 例如键查找 ),而在其他情况下(迭代和调整大小会浮现在脑海中)应该会出现性能提升。

总的来说,字典的性能,特别是在现实生活中,由于引入的紧凑性而得到改善。


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

我应该在Python 3.6中使用 dict 还是 OrderedDict

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

这个新实现的顺序保留方面被认为是一个实现细节,不应该依赖它

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

让您的代码面向未来:)

这里有一个关于这个问题的辩论。

编辑: Python 3.7将保持这个功能 see


更新:Guido van Rossum guaranteed Python 3.7开始,所有Python实现中的 dict 必须保留插入顺序。





python-3.6