如何查询random.random()使用的种子?

mix*_*mix 41 python random seed

有没有办法找出Python用于播种其随机数生成器的种子?

我知道我可以指定自己的种子,但我很高兴Python管理它.但是,我确实想知道它使用了什么种子,所以如果我喜欢我在特定运行中获得的结果,我可以在以后重现该运行.如果我有种子,那么我可以.

如果答案是我不能,那么自己生成种子的最佳方法是什么?我希望它们总是与不同的运行方式不同 - 我只是想知道使用了什么.

更新:是的,我的意思是random.random()!错误... [标题更新]

Zoo*_*oba 41

不可能从发电机中取出自动种子.我通常生成这样的种子:

seed = random.randrange(sys.maxsize)
rng = random.Random(seed)
print("Seed was:", seed)
Run Code Online (Sandbox Code Playgroud)

这种方式是基于时间的,所以每次运行脚本(手动)都会有所不同,但如果你使用多个生成器,它们就不会有相同的种子,因为它们几乎是同时创建的.

  • @Glenn Maynard除非你想知道种子是什么,否则你可以在以后重现生成的序列. (16认同)
  • 在Python3 +中使用sys.maxsize作为sys.maxint已被删除 (8认同)
  • 默认情况下,PRNG会自动从OS的PRNG播种(通过`os.urandom`),因此这几乎总是不必要的. (2认同)
  • Python 缺少 *`random.getseed()`*,但这比 [Java 中的等价物] 痛苦得多(http://stackoverflow.com/questions/6001368/how-do-i-get-the-seed -from-a-random-in-java)。 (2认同)
  • @CharlieParker 我在看到 Brendan 的评论后更新了我的答案,这就是为什么它在答案中说“maxsize”。以前它使用`maxint` (2认同)

Gle*_*ard 26

随机数生成器的状态并不总是简单的种子.例如,安全PRNG通常具有熵缓冲器,其是更大的数据块.

但是,您可以保存并恢复randon数字生成器的整个状态,以便稍后可以在以下位置重现其结果:

import random

old_state = random.getstate()
print random.random()

random.setstate(old_state)
print random.random()

# You can also restore the state into your own instance of the PRNG, to avoid
# thread-safety issues from using the default, global instance.
prng = random.Random()
prng.setstate(old_state)
print prng.random()
Run Code Online (Sandbox Code Playgroud)

getstate当然,如果你想永久保存它,可以腌制结果.

http://docs.python.org/library/random.html#random.getstate

  • @Zooba:那些是等价的.要从蛋挞中重现整个序列,只需将PRNG的状态存储在该点即可. (8认同)
  • 鉴于问题的上下文(可选的每次播种)存储相对较大的状态元组远非最佳.单个种子值更容易嵌入配置数据中,如果您需要安全的PRNG,则无论如何都不应保存种子(或状态). (6认同)
  • 这在技术上是正确的,但 Zooba 的方法对于 OP 的目的来说更加用户友好。 (2认同)
  • @smci:他的方法是不必要的不​​安全,大大减少了可用的随机性.(并且你不应该存储安全PRNG状态的想法是无稽之谈 - 你可以说你不应该为HTTPS服务器存储私钥.) (2认同)

Luc*_*ira 12

你可以将random.Random子类化,以与python相同的方式重写seed()方法(本例中为v3.5),但在调用super()之前将种子值存储在变量中:

    import random

    class Random(random.Random):
        def seed(self, a=None, version=2):
            from os import urandom as _urandom
            from hashlib import sha512 as _sha512
            if a is None:
                try:
                    # Seed with enough bytes to span the 19937 bit
                    # state space for the Mersenne Twister
                    a = int.from_bytes(_urandom(2500), 'big')
                except NotImplementedError:
                    import time
                    a = int(time.time() * 256) # use fractional seconds

            if version == 2:
                if isinstance(a, (str, bytes, bytearray)):
                    if isinstance(a, str):
                        a = a.encode()
                    a += _sha512(a).digest()
                    a = int.from_bytes(a, 'big')

            self._current_seed = a
            super().seed(a)

        def get_seed(self):
            return self._current_seed
Run Code Online (Sandbox Code Playgroud)

如果你测试它,使用新种子生成的第一个随机值和使用相同种子生成的第二个值(使用我们创建的get_seed()方法)将是相同的:

    >>> rnd1 = Random()
    >>> seed = rnd1.get_seed()
    >>> v1 = rnd1.randint(1, 0x260)
    >>> rnd2 = Random(seed)
    >>> v2 = rnd2.randint(1, 0x260)
    >>> v1 == v2
    True
Run Code Online (Sandbox Code Playgroud)

如果您存储/复制巨大的种子值并尝试在另一个会话中使用它,则生成的值将完全相同.

  • 没有多少人赞赏这种方法.这个解释很棒. (3认同)

Cha*_*ker 6

由于没有人提到通常在任何编程语言中可以获得的最佳随机样本是通过操作系统生成的,因此我必须提供以下代码:

random_data = os.urandom(8)
seed = int.from_bytes(random_data, byteorder="big")
Run Code Online (Sandbox Code Playgroud)

这是加密安全的。

来源:https : //www.quora.com/What-is-the-best-way-to-generate-random-seeds-in-python


值为 8 时,它似乎产生与sys.maxsize我相同数量的数字。

>>> int.from_bytes(os.urandom(8), byteorder="big")
17520563261454622261
>>> sys.maxsize
9223372036854775807
>>>
Run Code Online (Sandbox Code Playgroud)


Dr.*_*rew 5

如果您使用 来“设置”种子random.seed(None),则随机发生器会自动作为系统时间的函数进行播种。但是,正如您所观察到的,您无法访问此值。当我想随机化但仍然知道种子是这样的时,我会怎么做:

tim = datetime.datetime.now()
randseed = tim.hour*10000+tim.minute*100+tim.second
random.seed(randseed)
Run Code Online (Sandbox Code Playgroud)

注意:我更喜欢time.time()按照@Abdallah 的建议使用它的原因是因为这种方式 randseed 是人类可读的并且可以立即理解,这通常有很大的好处。还可以根据需要添加日期组件甚至微分段。