python dict str() 函数是不是可靠地对键进行排序?

Posted

技术标签:

【中文标题】python dict str() 函数是不是可靠地对键进行排序?【英文标题】:is the python dict str() function reliably sorting keys?python dict str() 函数是否可靠地对键进行排序? 【发布时间】:2012-01-07 12:47:20 【问题描述】:

在 python 中,字典 1:1,2:2,3:33:3,2:2,1:1 在 str()'d 时产生 "1:1,2:2,3:3"

我是否可以依靠这种排序,或者至少依靠包含相同键/值对的字典在通过 str() 函数时会生成相同的字符串这一事实?

【问题讨论】:

【参考方案1】:

您不能依赖这两个属性。字典转换为字符串时的顺序还取决于键/值对的插入顺序。

只要对 Python 源代码有一点了解(观看 PyCon 2010 中的 The Mighty Dictionary),或者进行一些反复试验,您就可以轻松找到反例:

>>> 1: 1, 9: 9
1: 1, 9: 9
>>> 9: 9, 1: 1
9: 9, 1: 1

【讨论】:

'排序顺序'有点误导,因为字典甚至没有 ordered 更不用说排序了。 @AaronGallagher:我没有说“排序顺序”,我说的是“转换为字符串时字典的排序顺序”。它们肯定在字符串输出中以 some 的顺序排列。你有更好的措辞的建议吗? (英语不是我的母语。) 好的,'some order' 也不同于'sort order'。为什么不完全删除“排序”这个词?没有排序。【参考方案2】:

dict 内置类型不保证键的任何特定顺序。

即使您似乎总是得到相同的字符串,也不要依赖它。如果你这样做了,当你升级 Python 时,实现中可能会发生变化,导致你的假设失败。

OrderedDict 类确实提供有关键顺序的保证。

【讨论】:

是的,但是 repr 方法仍然可以按排序顺序列出项目。事实并非如此。 @Cito:正如 Mark Byers 在他的回答中提到的以及我从 Mark Lutz 的书中引用的那样,dict 没有任何顺序,__repr__ 方法也没有。当整个数据类型不能保证时,通过键对__repr__结果进行排序将毫无意义。 不,这不是没有意义的。这通常会有所帮助,例如用于文档测试。我猜它没有完成的原因是额外的排序成本性能+内存和键并不总是有意义的排序。【参考方案3】:

不,你不能。试试这个:

 i:i for i in range(0, 100, 10) 

它适用于从零开始的连续整数的原因是每个整数都对其自身进行哈希处理 (hash(i) == i),并且字典会将其内部表的大小至少与它们所持有的元素一样大(它们使用探测策略,这需要这个)。因此,整数 i 最终在插槽 i 中没有冲突。您还会发现,从某个其他数字开始的连续整数也倾向于单调递增,但它们可能会在中间某处回绕:

>>>  i:'' for i in range(25, 35) 
32: '', 33: '', 34: '', 25: '', 26: '', 27: '', 28: '', 29: '', 30: '', 31: ''

请务必注意,这些只是对实际行为的观察。语言中没有任何东西可以保证这一切,所以你不能依赖它。

【讨论】:

【参考方案4】:

不,你不能依赖它。如Learning Python. 4th Edition by Mark Lutz(第 94 页)所述:

(...) 因为字典不是序列,它们不维护任何 可靠的从左到右的顺序。这意味着如果我们制作字典并打印它 返回,它的键可能会以不同于我们输入它们的顺序返回 (...)

但是,书中提到了另一种按键顺序打印键值对的解决方案(D 是您要发送的字典):

>>> for key in sorted(D):
    print(key, '=>', D[key])

通过使用上述方法,您可以以任何您喜欢的方式打印项目,甚至可以创建一些包含有序元素的序列,如下所示:

>>> D = 'a': 12, 'b': 65, 7: 'asd'
>>> S = [(key, D[key]) for key in sorted(D)]
>>> S
[(7, 'asd'), ('a', 12), ('b', 65)]

S 中的项目顺序是可靠的(您可以依赖它,因为在您明确更改之前它不会改变)。

【讨论】:

以上是关于python dict str() 函数是不是可靠地对键进行排序?的主要内容,如果未能解决你的问题,请参考以下文章

Python字典

python学习第二天

廖雪峰python摘录4

JSON 对象必须是 str、bytes 或 bytearray,而不是 dict

python3 json数据格式的转换(dumps/loads的使用dict to str/str to dictjson字符串/字典的相互转换)

Python中的迭代器