【发布时间】:2018-09-28 11:43:58
【问题描述】:
Python 2
集合是无序值的集合。如果我通过集合文字构造集合,例如
s = {'a', 'b', 'c'}
然后打印出来,我得到了一些乱序的元素。但是,在 Python 2.7 中,上面的示例似乎总是导致相同的排序:
print(s) # set(['a', 'c', 'b']) in Python 2.7
Python 2.7 如何决定这个顺序?甚至'a'、'b' 和'c' 的哈希值也不按生成顺序。
Python 3
在 Python 3.x(包括对 dict 键进行排序的 3.6)中,生成的顺序似乎是随机的,尽管在给定的 Python 进程中总是相同的。也就是说,只要我不重新启动 Python 解释器,反复重新构建集合文字总是会导致相同的顺序。
要检查多个 Python 进程的顺序,请考虑 bash 代码
(for _ in {1..50}; do python3 -c "s = {'a', 'b', 'c'}; print(s)"; done) | sort -u
这将(通常)显示 3 个元素的 6 种不同排列方式。用python(2) 切换出python3,我们只看到排序['a', 'c', 'b']。什么决定了 Python 3 中的顺序?
我发现对象的 hash 值在 Python 2 中是确定性的,而在 Python 3 中是随机的(尽管在 Python 进程中是恒定的)。我相信这是完整解释的关键。
编辑
正如 deceze 在他的评论中所写,我想知道 Python 是否明确地做了一些事情来实现这种随机化,或者它是否“免费”发生。
【问题讨论】:
-
有什么意义?您不应该依赖集合或字典的特定顺序。如果你需要,你应该使用OrderedDict。此外,您发现的散列行为与它应该具有散列函数的属性一致。如果您需要确定性哈希,请实现您自己的。
-
预计在确定性算法中会有一些顺序,除非 Python 不遗余力地故意随机化该顺序。
-
虽然这些字符的完整哈希值不是按这个顺序排列的,但它们的低位是!对于基于散列的小型容器,python 只使用那些低位。
-
@Wombatz 谢谢,这是一个相当大的难题。
标签: python python-3.x python-2.7 set non-deterministic