为何itertools.repeat生成相同随机数?如何实现每次生成新随机数?
为什么itertools.repeat生成重复随机数?怎么解决?
先看两个对比函数:
from itertools import repeat import numpy as np def rand_list1(): l = lambda: np.random.rand(3) return list(repeat(l(), 5)) def rand_list2(): return [np.random.rand(3) for i in range(5)]
现象
调用rand_list1()会得到5个完全相同的3维随机数组:
[[0.07678796 0.22623777 0.07533145] [0.07678796 0.22623777 0.07533145] [0.07678796 0.22623777 0.07533145] [0.07678796 0.22623777 0.07533145] [0.07678796 0.22623777 0.07533145]]
而rand_list2()的输出是5个不同的随机数组:
[[0.77863856 0.30345662 0.7007517 ] [0.56422447 0.97138115 0.47976387] [0.20576279 0.92875791 0.06518335] [0.2992384 0.89726684 0.16917078] [0.8440534 0.38016789 0.51691172]]
原因
问题出在repeat(l(), 5)这行:
l()是立即执行的,调用repeat的时候,已经生成了一个随机数组,repeat做的只是把这个已经生成的数组对象重复5次,本质上列表里的5个元素都是同一个数组的引用。- 而列表推导式
[np.random.rand(3) for i in range(5)]是循环5次,每次循环都会重新调用np.random.rand(3)生成新的随机数,所以每个元素都是独立的。
解决方法
要让repeat每次都生成新的随机数,不能直接传l()(执行后的结果),而是要传可调用对象(比如函数本身),然后在遍历的时候触发调用。
方法1:用生成器表达式遍历repeat的可调用对象
def rand_list1(): l = lambda: np.random.rand(3) # 遍历repeat传递的函数对象,每次调用生成新随机数 return [func() for func in repeat(l, 5)]
方法2:用map配合repeat
def rand_list1(): l = lambda: np.random.rand(3) # map会对repeat里的每个函数对象执行调用 return list(map(lambda x: x(), repeat(l, 5)))
方法3:直接传递np.random.rand函数
甚至可以省略lambda,直接把np.random.rand作为可调用对象传进去,指定参数:
def rand_list1(): return [func(3) for func in repeat(np.random.rand, 5)]
修改后再调用rand_list1(),就能得到和rand_list2()一样的效果——每个元素都是独立生成的随机数组。
内容的提问来源于stack exchange,提问作者proton
相关产品推荐
相关产品推荐

