我的问题与What is the scope of a random seed in Python?有关。
对于上述问题,需要说明的是,模块Random()
中有一个(隐藏的)全局random
实例。
1)我想澄清的是,在一个模块中设置随机种子是否会导致它成为 other 模块中的随机种子,以及是否需要注意某些事情。
例如: 给定:moduleA.py,moduleB.py
moduleA.py:
import random
import moduleB
random.seed(my_seed)
moduleB.randomfct()
moduleB.py:
import random
def randomfct():
#do_things_using_random
moduleB是否也使用my_seed
,还是我必须将种子传递给moduleB.py并重新设置?
2)设置随机种子/导入的顺序是否起作用?
例如在moduleA.py
中:
import random
random.seed(my_seed)
import moduleB
3)设置numpy个随机种子也是这种情况,例如np.random.seed(42)
?
答案 0 :(得分:3)
CPython random.py
实现非常易读。我建议您看看:https://github.com/python/cpython/blob/3.6/Lib/random.py
无论如何,该版本的python创建一个全局random.Random()
对象,并将其直接分配给random
模块。该对象包含一个seed(a)
方法,当您调用random.seed(a)
时该方法acts as a module function。因此,种子状态会在整个程序中共享。
1)是。 moduleA
和moduleB
使用相同的种子。在random
中导入moduleA
会创建全局random.Random()
对象。在moduleB
中重新导入它只会为您提供相同的模块并维护最初创建的random.Random()
对象。
2)否。不是您所举的示例,但总的来说,这很重要。在设置moduleB
中的种子之前,您可以使用moduleA
,这样就不会设置种子。
3)很难说。更复杂的代码库。也就是说,我认为它的工作方式相同。 numpy的作者确实必须 try 来使其工作方式不同于python实现中的工作方式。
通常,如果您担心种子状态,建议您创建自己的随机对象并将其传递以生成随机数。
答案 1 :(得分:1)
因此,回答第一个问题:
moduleB是否也使用my_seed,还是我必须将种子传递给moduleB.py并重新设置?
是的,例如,运行以下命令:
ModuleA:
import moduleb
import random
random.seed(0)
my_random()
ModuleB
import random
def my_random():
print(random.randint(0,5))
设置种子后,它将始终打印3。 一般规则是必须运行的主要python模块应调用random.seed()函数,这将创建一个种子,该种子在所有导入的模块之间共享。 仅当您从其他模块再次显式调用random.seed时,此更改才会更改。
问题2:
设置随机种子/导入的顺序是否起作用?
不,不是。除非您在设置种子之前调用random函数。
问题3:
设置numpy随机种子也是这种情况,例如np.random.seed(42)?
因此,使用np.random.seed()带来的问题是它们不是线程安全的,这就是为什么它们的行为不同。可以在以下位置找到更多详细信息: This Stackoverflow answer
答案 2 :(得分:1)
在jupyter笔记本中,random.seed似乎具有单元格范围。 例如,需要在两个连续的单元格中都指定random.seed(1),以使用以下代码获得相同的结果:
单元格1:
np.random.seed(1)
np.random.random_sample(4)
单元2:
np.random.seed(1)
np.random.random(4)