set没有顺序但random.choice(list(set))在给定随机种子时是不稳定的

时间:2018-01-01 10:12:47

标签: python python-3.x

我在我的项目中找到了以下代码的奇怪结果(下面的代码相当于我项目中的代码,因为我必须删除与问题无关的部分):

import random
random.seed(9000)

...
list1 = [0, 1]
list2 = []
set_diff = set(list1) - set(list2)
print( set_diff )
list_diff = list( set_diff )
print( list_diff )
print( random.choice( list_diff ) )

结果不稳定,因为set_diff的顺序(如打印)不稳定(设置应该没有顺序)。结果可能是:

{'0', '1'}
['0', '1']
1

{'1', '0'}
['1', '0']
0

在不同的运行中。 有人可以解释一下原因吗?谢谢!

1 个答案:

答案 0 :(得分:1)

集合是无序的,因此将以任何顺序生成其元素。但是,此顺序在一次python调用中是一致的。也就是说,set_ = set(range(N)); list(set_) == list(set_)在同一个python程序中始终是真的。 Python 3.2+明确地确保从一个python实例到下一个python实例的排序不一致(这是与涉及字典构造的拒绝服务攻击有关的安全性考虑)。这就是你所看到的行为。

为避免这种情况,您需要在启动程序之前将环境变量PYTHONHASHSEED设置为相同的值。这是在使用random.choice之前设置随机种子的补充。

export PYTHONHASHSEED=1
python myscript.py

然而,更简单的解决方案是在执行random.choice之前创建排序列表。即。

random.choice(sorted({1, 2, 3}))