有没有办法找出python用来给随机数生成器种子的种子是什么?
我知道我可以指定我自己的种子,但是我很满意Python管理它。但是,我确实想知道它使用了什么种子,这样如果我喜欢在特定运行中得到的结果,我可以稍后复制该运行。如果我有使用过的种子,我可以。
如果答案是我做不到,那我自己种下种子的最好方法是什么?我想让他们从一个跑步到另一个跑步,我只想知道使用了什么。
更新:是的,我的意思是随机。随机()!错误…[更新标题]
什么是math.random()?你是说random.random()吗?
因为要把原始种子取回来并不容易,所以我只需要自己从操作系统中生成一个,例如seed = int.from_bytes(os.urandom(8), byteorder="big")。
无法从发电机中取出自动种子。我通常会产生这样的种子:
seed = random.randrange(sys.maxsize)
rng = random.Random(seed)
print("Seed was:", seed)
这样,它是基于时间的,所以每次运行脚本(手动)时都会有所不同,但是如果使用多个生成器,它们将不会有相同的种子,因为它们几乎是同时创建的。
默认情况下,prng是从操作系统的prng中自动播种的(通过os.urandom),因此这几乎总是不必要的。
@格伦·梅纳德,除非你想知道种子是什么样的,这样你以后就能复制产生的序列。
Python缺乏EDOCX1,1,但这比在爪哇相当痛苦。
在python3+中,使用sys.maxsize,因为已删除sys.maxint
你的播种方式与:seed = ord(os.urandom(1))相比如何?
@Brendanmaguire你在说什么,你可以使用sys.maxsize,据我在python中所说,Python 3.6.3 |Anaconda custom (64-bit)| (default, Nov 3 2017, 19:19:16)可以使用sys.maxsize 9223372036854775807。
@查理帕克,我在看到布兰登的评论后更新了我的答案,这就是为什么答案中说是maxsize。以前用过maxint。
随机数生成器的状态并不总是简单的种子。例如,安全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()
号
当然,如果你想持续保存,那么getstate的结果可以被腌制。
http://docs.python.org/library/random.html random.getstate
这不会重现一个序列,只会让你从上次停止的地方继续。如果您想从一开始就复制整个序列,您需要知道seed值。
@祖巴:这些是等效的。要从tart复制整个序列,只需在该点存储prng的状态。
考虑到问题的上下文(可选的每次运行种子设定),存储相对较大的状态元组远不是最佳的。单个种子值更容易嵌入到配置数据中,如果需要安全的prng,则无论如何都不应该保存种子(或状态)。
这在技术上是正确的,但Zooba的方法对于OP的目的来说更加用户友好。
@他的方法不必要地缺乏安全感,大大减少了随机性。(不应该存储安全prng的状态的想法是胡说八道的——你也可以说不应该存储https服务器的私钥。)
@格伦:哦,好的。当时我的评论是错误的。
您可以将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
如果您存储/复制巨大的种子值并尝试在另一个会话中使用它,则生成的值将完全相同。
没有多少人欣赏这种方法。这个解释太离谱了。
如果使用random.seed(None)来"设置"种子,随机化器将自动作为系统时间的函数进行种子设定。但是,正如您观察到的,您不能访问这个值。当我想随机化但仍然知道种子是这样的时候,我要做的是:
tim = datetime.datetime.now()
randseed = tim.hour*10000+tim.minute*100+tim.second
random.seed(randseed)
。
注:我之所以喜欢使用@abdallah提出的time.time(),是因为通过这种方式,randseed具有人类可读性和可立即理解性,这通常有很大的好处。还可以根据需要添加日期组件甚至微段。
我也想做同样的事,但我得不到种子。所以,我想,因为种子是由时间产生的。我使用系统时间创建了我的种子,并将其用作种子,所以现在我知道使用了哪个种子。
SEED = int(time.time())
random.seed(SEED)
由于没有人提到,在任何编程语言中通常可以获得的最佳随机样本是通过操作系统生成的,因此我必须提供以下代码:
random_data = os.urandom(8)
seed = int.from_bytes(random_data, byteorder="big")
。
这在密码学上是安全的。