代码之家  ›  专栏  ›  技术社区  ›  Adrian McCarthy

设置迭代顺序因运行而异

  •  20
  • Adrian McCarthy  · 技术社区  · 14 年前

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

    不幸的是,这破坏了我的一个自动化测试,它只是比较两次运行程序的输出。我不在乎实际的顺序,但我希望每次都保持一致。

    我想到的最佳解决方案是:

    1. 将集合复制到列表中。
    2. 对列表应用任意排序。
    3. 迭代列表而不是集合。

    有更简单的解决办法吗?

    7 回复  |  直到 7 年前
        1
  •  13
  •   Turtle    14 年前

    我的解决方案和你的一样,如果你想把它和另一个比较,你必须对集合进行排序。

        2
  •  18
  •   Adrian McCarthy    9 年前

    -R 因此,set迭代不仅是任意的(因为散列),而且是不确定的(因为随机种子)。

    通过设置环境变量,可以用固定值覆盖随机种子 PYTHONHASHSEED 为口译员。从一次运行到另一次运行使用相同的种子意味着集合迭代仍然是任意的,但现在它是确定性的,这是所需的属性。

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

        3
  •  16
  •   Brian C. Lane    14 年前

    在两个集合上使用symmetric\u 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()
    
        4
  •  6
  •   Ned Batchelder    14 年前

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

        5
  •  4
  •   Community CDub    4 年前

    你的问题变成了两个问题:A)在你的具体案例中如何比较“两次运行的输出”;B)集合中迭代顺序的定义是什么。如果合适的话,也许你应该把它们区分开来,然后把B)作为一个新问题贴出来。我回答A。

    依我看,在你的案例中使用排序列表并不是一个非常干净的解决方案。您应该决定是否一次性地考虑迭代顺序,并使用适当的结构。

    或者1)您想比较这两个集合,看看它们的内容是否相等,而不考虑顺序。那么在集合上使用simple==运算符似乎是合适的。看到了吗 python2 sets python3 sets .

    或者2)检查元素是否按相同顺序插入。但是,只有当插入顺序对库的用户有某种影响时,这才显得合理,在这种情况下,使用set类型可能是不合适的。换句话说,不清楚“比较两次运行的输出”到底是什么意思,以及为什么要这样做。

    在所有情况下,我怀疑一个排序的列表在这里是合适的。

        6
  •  1
  •   Chuiwen Ma    8 年前

        7
  •  -1
  •   knitti freethinker    14 年前

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