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

2024-04-19 18:10:54 发布

您现在位置:Python中文网/ 问答频道 /正文


Tags: python
3条回答

无法将自动种子从生成器中取出。我通常会产生这样的种子:

seed = random.randrange(sys.maxsize)
rng = random.Random(seed)
print("Seed was:", seed)

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

随机数生成器的状态并不总是简单的种子。例如,安全PRNG通常有一个熵缓冲器,它是一个较大的数据块。

但是,您可以保存和还原randon number generator的整个状态,以便稍后可以复制其结果:

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()

当然,如果您想持久保存getstate的结果,可以对其进行pickle。

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

您可以将random.random子类化,像python那样重写seed()方法(在本例中是v3.5),但是在调用super()之前将seed值存储在变量中:

    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

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

    >>> rnd1 = Random()
    >>> seed = rnd1.get_seed()
    >>> v1 = rnd1.randint(1, 0x260)
    >>> rnd2 = Random(seed)
    >>> v2 = rnd2.randint(1, 0x260)
    >>> v1 == v2
    True

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

相关问题 更多 >