【问题标题】:How to write a Python program that gives the same output in every run?如何编写一个 Python 程序在每次运行时都给出相同的输出?
【发布时间】:2020-11-07 08:12:20
【问题描述】:

我有以下代码

import random

random.seed(42)

mylist = set(["A", "B", "C", "D", "E", "F", "G", "H"]) 
tn = random.sample(mylist, 4)
print(tn)

到目前为止,我预计这总是会打印相同的结果。但是,在每次连续运行时,它都会返回不同的 4 个字母序列。后来我发现它在删除 set 时是稳定的(在这个最小的例子中,除了触发问题之外没有其他目的)。

为什么有人会以不确定的方式实现set?我可以想象它的实现可能需要(伪)随机数,但即使那样我也希望我的程序仍然是确定性的,即使使用set。我还注意到这是版本相关的:

Python 版本:

  • 2.7.12:稳定
  • 3.5.2:不同的输出
  • 3.6.12:不同的输出

如何使用set 并且仍然获得可重现的输出?在采样工作之前对mylistsorted 进行排序,但是您必须对在(天真地)空操作之后再次排序的列表进行排序是非常不直观的。

【问题讨论】:

  • 未指定集合中元素的顺序,因此他们可能故意这样做是为了弄乱依赖特定顺序的应用程序。
  • 但是sorted() 给了你另一个列表,所以你输了。
  • 字符串 哈希 在运行之间不固定。
  • 如果你需要重现性,你真的需要做更少的假设。如果您尝试在不同的计算机上进行测试,这在 2.7.12 上也不会稳定 - 在 32 位和 64 位版本上散列是不同的。
  • 这已被 PEP 456 更改;哈希算法故意不可重现以关闭线性时间哈希表攻击。 python.org/dev/peps/pep-0456

标签: python random set random-seed


【解决方案1】:

您的期望很直观,但这不是语言规范的一部分。

未指定set 的哈希机制; Python 实现不需要重现散列映射——或使用任何机制。它可能取决于最近的存储使用情况、可用位置、系统时间或月相。

如果您对“作品”的个人定义需要可重现的映射,那么您有责任提供自己的映射,或使用支持这种稳定性的语言工具。排序不会给你设置稳定性;它用排序列表替换集合。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-02
    • 1970-01-01
    • 1970-01-01
    • 2021-10-17
    • 2014-12-06
    • 2021-11-14
    • 2015-11-10
    相关资源
    最近更新 更多