设置迭代顺序因运行而异

时间:2010-10-03 00:41:59

标签: python set iteration

为什么Python集的迭代顺序(具有相同的内容)因运行而异,以及从运行到运行使其一致的选项是什么?

我知道Python集的迭代顺序是任意的。如果我将'a','b'和'c'放入一个集合然后迭代它们,它们可能会以任何顺序返回。

我观察到的是,在程序运行中,订单保持不变。也就是说,如果我的程序连续两次迭代同一个集合,那么我两次都得到相同的顺序。但是,如果我连续两次运行程序,则顺序会从运行更改为运行。

不幸的是,这打破了我的一个自动化测试,它简单地比较了我的程序的两次运行的输出。我不关心实际的顺序,但我希望它在运行之间保持一致。

我提出的最佳解决方案是:

  1. 将该集复制到列表中。
  2. 对列表应用任意排序。
  3. 迭代列表而不是集合。
  4. 是否有更简单的解决方案?

    注意:我在StackOverlow上发现了类似的问题,但没有一个能解决从运行到运行获得相同结果的特定问题。

7 个答案:

答案 0 :(得分:14)

你想要的是不可能的。任意意味着任意。

我的解决方案与您的解决方案相同,如果您希望能够将其与另一个进行比较,则必须对该集进行排序。

答案 1 :(得分:14)

在两组上使用symmetric_difference(^)运算符来查看是否存在任何差异:

In [1]: s1 = set([5,7,8,2,1,9,0])
In [2]: s2 = set([9,0,5,1,8,2,7])
In [3]: s1
Out[3]: set([0, 1, 2, 5, 7, 8, 9])
In [4]: s2
Out[4]: set([0, 1, 2, 5, 7, 8, 9])
In [5]: s1 ^ s2
Out[5]: set()

答案 2 :(得分:10)

set迭代顺序从run-to-run更改的原因似乎是因为Python默认使用散列种子随机化。 (参见命令选项-R。)因此,设置迭代不仅是任意的(因为散列),而且也是非确定性的(因为随机种子)。

您可以通过为解释器设置环境变量PYTHONHASHSEED来覆盖具有固定值的随机种子。使用从run到run的相同种子意味着set iteration仍然是任意的,但现在它是确定性的,这是所需的属性。

哈希种子随机化是一种安全措施,使对手难以提供将导致病态行为的输入(例如,通过创建大量哈希冲突)。对于单元测试,这不是一个问题,因此在运行测试时覆盖散列种子是合理的。

答案 3 :(得分:5)

集合的迭代顺序不仅取决于其内容,还取决于项目插入集合的顺序,以及沿途是否有删除。因此,您可以使用不同的插入和删除创建两个不同的集合,最后使用相同的集合,但具有不同的迭代顺序。

正如其他人所说:如果你关心集合的顺序,你必须从中创建一个排序列表。

答案 4 :(得分:2)

您的问题转化为两个问题:A)如何在特定情况下比较“两次运行的输出”; B)集合中迭代顺序的定义是什么。也许你应该区分它们并将B)作为一个新问题发布。我会回答A.

恕我直言,在您的情况下使用排序列表不是一个非常干净的解决方案。您应该决定是否一劳永逸地关注迭代顺序并使用适当的结构。

要么1)你要比较两组,看看它们是否有相同的内容,不论顺序如何。那么简单的==运算符on sets似乎是合适的。请参阅python2 setspython3 sets

或者2)你想检查元素是否以相同的顺序插入。但是,只有当插入顺序在某种程度上对您的库的用户很重要时,这似乎是合理的,在这种情况下使用set类型可能不适合开始。换句话说,通过“比较两次运行的输出”以及为什么要这样做,目前还不清楚你的意思。

在所有情况下,我怀疑排序列表是否合适。

答案 5 :(得分:1)

您可以将预期结果设置为一组。并使用==检查这两组是否相等。

答案 6 :(得分:-1)

与集合相反,列表始终是有保证的顺序,因此您可以抛出集合并使用列表。