【发布时间】:2012-01-07 12:47:20
【问题描述】:
在 python 中,字典 {1:1,2:2,3:3} 和 {3:3,2:2,1:1} 在 str()'d 时产生 "{1:1,2:2,3:3}"?
我是否可以依靠这种排序,或者至少依靠包含相同键/值对的字典在通过 str() 函数时会生成相同的字符串这一事实?
【问题讨论】:
标签: python string dictionary
在 python 中,字典 {1:1,2:2,3:3} 和 {3:3,2:2,1:1} 在 str()'d 时产生 "{1:1,2:2,3:3}"?
我是否可以依靠这种排序,或者至少依靠包含相同键/值对的字典在通过 str() 函数时会生成相同的字符串这一事实?
【问题讨论】:
标签: python string dictionary
您不能依赖这两个属性。字典转换为字符串时的顺序还取决于键/值对的插入顺序。
只要对 Python 源代码有一点了解(观看 PyCon 2010 中的 The Mighty Dictionary),或者进行一些反复试验,您就可以轻松找到反例:
>>> {1: 1, 9: 9}
{1: 1, 9: 9}
>>> {9: 9, 1: 1}
{9: 9, 1: 1}
【讨论】:
dict 内置类型不保证键的任何特定顺序。
即使您似乎总是得到相同的字符串,也不要依赖它。如果你这样做了,当你升级 Python 时,实现中可能会发生变化,导致你的假设失败。
OrderedDict 类确实提供有关键顺序的保证。
【讨论】:
dict 没有任何顺序,__repr__ 方法也没有。当整个数据类型不能保证时,通过键对__repr__结果进行排序将毫无意义。
不,你不能。试试这个:
{ 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: ''}
请务必注意,这些只是对实际行为的观察。语言中没有任何东西可以保证这一切,所以你不能依赖它。
【讨论】:
不,你不能依赖它。如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 中的项目顺序是可靠的(您可以依赖它,因为在您明确更改之前它不会改变)。
【讨论】: