Python27:setstate()后面的random()不';t产生相同的随机数
我一直在对Python的随机数生成器进行子类化,以生成一个不重复结果的生成器(它将用于为模拟器生成唯一的id),我只是在测试它在从先前状态加载后的行为是否一致 在人们提问之前:Python27:setstate()后面的random()不';t产生相同的随机数,python,python-2.7,random,Python,Python 2.7,Random,我一直在对Python的随机数生成器进行子类化,以生成一个不重复结果的生成器(它将用于为模拟器生成唯一的id),我只是在测试它在从先前状态加载后的行为是否一致 在人们提问之前: 这是一个单身班 不,没有其他任何东西应该使用该实例(拆下后会看到) 是的,我在没有检查singleton实例的情况下测试了它 是的,当我创建这个子类时,我确实调用了一个新实例(super(nrand,self)。\uuuu init\uuu()) 是的,根据另一篇文章,我应该得到一致的结果,见: 下面是我的测试代码:
- 这是一个单身班
- 不,没有其他任何东西应该使用该实例(拆下后会看到)
- 是的,我在没有检查singleton实例的情况下测试了它
- 是的,当我创建这个子类时,我确实调用了一个新实例(
)super(nrand,self)。\uuuu init\uuu()
- 是的,根据另一篇文章,我应该得到一致的结果,见:
def test_stateSavingConsitantcy(self):
start = int(self.r.random())
for i in xrange(start):
self.r.random()
state = self.r.getstate()
next = self.r.random()
self.r.setstate(state)
nnext = self.r.random()
self.assertEqual(next, nnext, "Number generation not constant got {0} expecting {1}".format(nnext,next))
如能提供任何帮助,将不胜感激
编辑:
这是我请求的子类
class Singleton(type):
_instances = {}
def __call__(self, *args, **kwargs):
if self not in self._instances:
self._instances[self] = super(Singleton,self).__call__(*args,**kwargs)
return self._instances[self]
class nrRand(Random):
__metaclass__ = Singleton
'''
classdocs
'''
def __init__(self):
'''
Constructor
'''
super(nrRand,self).__init__()
self.previous = []
def random(self):
n = super(nrRand,self).random()
while n in self.previous:
n = super(nrRand,self).random()
self.previous.append(n)
return n
def seed(self,x):
if x is None:
x = long(time.time()*1000)
self.previous = []
count = x
nSeed = 0
while count < 0:
nSeed = super(nrRand,self).random()
count -= 1
super(nrRand,self).seed(nSeed)
while nSeed < 0:
super(nrRand,self).seed(nSeed)
count -= 1
def getstate(self):
return (self.previous, super(nrRand,self).getstate())
def setstate(self,state):
self.previous = state[0]
super(nrRand,self).setstate(state[1])
类单例(类型):
_实例={}
定义调用(self,*args,**kwargs):
如果self不在self.\u实例中:
self.\u实例[self]=super(单例,self)。\u调用(*args,**kwargs)
返回self.\u实例[self]
类别nrRand(随机):
__元类\单例
'''
类文档
'''
定义初始化(自):
'''
建造师
'''
超级(nRand,self)。\uuuu init\uuuuuu()
self.previous=[]
def随机(自):
n=super(nrand,self).random()
而n在self.previous中:
n=super(nrand,self).random()
self.previous.append(n)
返回n
def种子(自身,x):
如果x为无:
x=长(time.time()*1000)
self.previous=[]
计数=x
nSeed=0
当计数小于0时:
nSeed=super(nrand,self).random()
计数-=1
超级(nRand,self).种子(NSED)
当NSED<0时:
超级(nRand,self).种子(NSED)
计数-=1
def getstate(自身):
返回(self.previous,super(nrand,self.getstate())
def设置状态(自身、状态):
self.previous=状态[0]
超级(nRand,self).setstate(状态[1])
getstate
和setstate
只操作随机
类知道的状态;这两种方法都不知道还需要回滚以前生成的数字集。您正在回滚从Random
继承的状态,但是对象看到它已经生成了下一个数字并跳过它。如果希望getstate
和setstate
正常工作,则必须覆盖它们以设置已生成数字集的状态
更新:
def getstate(self):
return (self.previous, super(nrRand,self).getstate())
这不应该直接使用self.previous
。由于您没有制作副本,因此返回的是用于跟踪生成的数字的实际对象。当RNG产生一个新号码时,由getstate
返回的状态将反映新号码。您需要复制self.previous
,如下所示:
def getstate(self):
return (self.previous[:], super(nrRand, self).getstate())
我还建议在setstate
中复制:
def setstate(self, state):
previous, parent_state = state
self.previous = previous[:]
super(nrRand, self).setstate(parent_state)
我应该提到的是,当我设置并获得状态时,我会确保重置该列表。啊,非常感谢你犯了这样一个简单而愚蠢的错误。你能分享你的子类吗?您是否在没有子类的情况下进行了测试?直接在
random
模块上使用测试代码会产生预期的输出,所以错误就在你的代码中。@MartijnPieters:不,我没有这样做,因为我的工作假设链接帖子的行为仍然成立,并且我对随机数生成器在大多数情况下的工作方式有偏见(即使用相同的起始种子,你应该得到相同的数字集)。不管怎样,我已经共享了我的子类。所以,如果您恢复self.previous
,为什么您希望它生成两个相同的值?