Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 设置迭代顺序因运行而异_Python_Set_Iteration - Fatal编程技术网

Python 设置迭代顺序因运行而异

Python 设置迭代顺序因运行而异,python,set,iteration,Python,Set,Iteration,为什么Python集(具有相同内容)的迭代顺序在不同的运行中有所不同,我有哪些选项可以使它在不同的运行中保持一致 我知道Python集合的迭代顺序是任意的。如果我把‘a’、‘b’和‘c’放到一个集合中,然后迭代它们,它们可能会以任何顺序返回 我观察到的是,在程序运行期间,顺序保持不变。也就是说,如果我的程序在一行中迭代同一集合两次,那么两次的顺序都相同。但是,如果我连续两次运行该程序,则顺序会随着运行而变化 不幸的是,这破坏了我的一个自动测试,它只是比较了我的两次程序运行的输出。我不关心实际的顺

为什么Python集(具有相同内容)的迭代顺序在不同的运行中有所不同,我有哪些选项可以使它在不同的运行中保持一致

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

我观察到的是,在程序运行期间,顺序保持不变。也就是说,如果我的程序在一行中迭代同一集合两次,那么两次的顺序都相同。但是,如果我连续两次运行该程序,则顺序会随着运行而变化

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

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

  • 将集合复制到列表中
  • 对列表应用任意排序
  • 迭代列表而不是集合
  • 有更简单的解决方案吗


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

    您想要什么是不可能的。武断就是武断


    我的解决方案与你的解决方案相同,如果你想将集合与另一个集合进行比较,你必须对集合进行排序。

    与集合相反,列表总是有保证的顺序,因此你可以丢弃集合并使用列表

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


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

    在你的两个集合上使用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()
    

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

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

    1)您想比较这两个集合,看看它们的内容是否相等,而不考虑顺序。那么,集合上的simple==运算符似乎是合适的。见

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


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

    设置迭代顺序从一次运行到另一次运行的原因似乎是Python默认使用散列种子随机化。(请参阅命令选项。)因此,集合迭代不仅是任意的(因为散列),而且是不确定的(因为随机种子)

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


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

    您可以将预期结果也设置为一个集合。然后用==,检查这两个集合是否相等。

    我想我假设武断意味着它取决于内容,而不是月亮的相位。好吧,有武断的,也有不确定性的。也许有一种方法可以确定场景中的顺序,但我敢打赌这会带来更多麻烦。检查一个有序的集合,或者python中的类似集合……即使它在不同的运行中是一致的,也不能保证机器之间、python版本之间、cpython与jython之间是一致的。即使在同一台机器上的相同python构建中,“相同的内容”也不能保证。根据哈希值插入项目。当多个项目具有相同的散列值时,它们会根据插入顺序插入到不同的位置。删除项目可能会导致更多不同的排序。还有一些项目的散列值取决于它们的内存位置,这使得运行之间有所不同。除了使用
    sorted()
    以方便的方式编写这三个步骤之外,您可以做的不多。不确定,但我猜在某些情况下,事情会按地址(即按id()进行散列),系统中的一些异步事情会以不同的方式在运行时干扰内存管理器。我不希望cpython在散列中包含PRNG。如果您测试的是“程序两次输出相同的内容”,那么排序列表选项是您最好的选择。如果你要测试的是“程序两次都创建了相同的集合”,你需要进行集合比较(通过对两次运行的输出进行酸洗,然后对两次运行的输出进行解酸洗,并对它们进行集合比较,或者做一些道德上等价的事情)。@Russell:我有验证集合内容的单元测试。但是我还有一个测试,它比较两次运行的输出,作为一个健全性检查。输出部分取决于集合中项目的顺序,但仅在一轮中