Python 2 和 3 中的不确定集
Indeterministic sets in Python 2 and 3
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 中(包括 3.6,其中 dict
键被排序)结果顺序似乎是随机的,尽管在给定的 Python 过程中总是相同的.也就是说,只要我不重新启动 Python 解释器,反复重新构建设置文字总是会导致相同的排序。
要检查多个 Python 进程的顺序,请考虑 bash 代码
(for _ in {1..50}; do python3 -c "s = {'a', 'b', 'c'}; print(s)"; done) | sort -u
这将(通常)显示 3 个元素的 6 种不同排列方式。将 python3
换成 python
(2),我们只能看到顺序 ['a', 'c', 'b']
。什么决定了 Python 3 中的顺序?
我看到对象的 hash
值在 Python 2 中是确定性的,而在 Python 3 中是随机的(尽管在 Python 过程中是常数)。我'我确定这是完整解释的关键。
编辑
正如 deceze 在他的评论中所写,我想知道 Python 是否明确地做了一些事情来实现这种随机化,或者它是否发生了 "for free".
Python 3(从 Python 3.3 开始)不同的原因是默认启用哈希随机化,您可以通过设置 PYTHONHASHSEED
环境来关闭它变量为固定值:
$ export PYTHONHASHSEED=0
$ (for _ in {1..50}; do python3 -c "s = {'a', 'b', 'c'}; print(s)"; done) | sort -u
{'a', 'b', 'c'}
同样,您可以使用 -R
flag:
在 Python 2 中打开哈希随机化
$ (for _ in {1..50}; do python2 -R -c "s = {'a', 'b', 'c'}; print(s)"; done) | sort -u
set(['a', 'b', 'c'])
set(['a', 'c', 'b'])
set(['b', 'c', 'a'])
set(['c', 'b', 'a'])
请注意,您通常不想将其关闭,因为启用哈希随机化有助于防止某些拒绝服务攻击。
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 中(包括 3.6,其中 dict
键被排序)结果顺序似乎是随机的,尽管在给定的 Python 过程中总是相同的.也就是说,只要我不重新启动 Python 解释器,反复重新构建设置文字总是会导致相同的排序。
要检查多个 Python 进程的顺序,请考虑 bash 代码
(for _ in {1..50}; do python3 -c "s = {'a', 'b', 'c'}; print(s)"; done) | sort -u
这将(通常)显示 3 个元素的 6 种不同排列方式。将 python3
换成 python
(2),我们只能看到顺序 ['a', 'c', 'b']
。什么决定了 Python 3 中的顺序?
我看到对象的 hash
值在 Python 2 中是确定性的,而在 Python 3 中是随机的(尽管在 Python 过程中是常数)。我'我确定这是完整解释的关键。
编辑
正如 deceze 在他的评论中所写,我想知道 Python 是否明确地做了一些事情来实现这种随机化,或者它是否发生了 "for free".
Python 3(从 Python 3.3 开始)不同的原因是默认启用哈希随机化,您可以通过设置 PYTHONHASHSEED
环境来关闭它变量为固定值:
$ export PYTHONHASHSEED=0
$ (for _ in {1..50}; do python3 -c "s = {'a', 'b', 'c'}; print(s)"; done) | sort -u
{'a', 'b', 'c'}
同样,您可以使用 -R
flag:
$ (for _ in {1..50}; do python2 -R -c "s = {'a', 'b', 'c'}; print(s)"; done) | sort -u
set(['a', 'b', 'c'])
set(['a', 'c', 'b'])
set(['b', 'c', 'a'])
set(['c', 'b', 'a'])
请注意,您通常不想将其关闭,因为启用哈希随机化有助于防止某些拒绝服务攻击。