[Tutor] Data persistence problem

Steven D'Aprano steve at pearwood.info
Sat Jun 22 11:11:07 CEST 2013


On 22/06/13 00:32, Wolfgang Maier wrote:
> Arijit Ukil <arijit.ukil <at> tcs.com> writes:
>
>>
>> I have following random number generation
>> function
>> def
>> rand_int ():
>>      rand_num = int(math.ceil
>> (random.random()*1000))
>>      return
>> rand_num
>> I like to make the value of rand_num
>> (return of rand_int) static/ unchanged after first call even if it is called
>> multiple times. If x=  rand_int () returns 45 at the first call, x
>> should retain 45 even in multiple calls.
>
> Sifting through the random module documentation a bit:
>
> def rand_int(update=False):
>      if update:
>          dummy = random.random()
>      oldstate=random.getstate()
>      rand_num = random.randint(0,1000)
>      random.setstate(oldstate)
>
>      return rand_num
>
> This will return a constant number when called with a False value for update
> (the default), but will switch to returning a new number when called
> with a True value once.


You really don't want to do this! By doing this, every time you call your rand_int() function, you will reset the application-wide pseudo-random number generator, possibly making a mess of other parts of your application and the standard library.

You also throw away a random value, which probably won't make a difference for the default Python PRNG, but may be bad if you're using a lousy PRNG.

There is a much simpler ways of doing this (see below), but if you must use getstate and setstate, then you should create your own personal random number generator rather than use the system-wide default PRNG.


myrandom = random.Random()

def rand_int(update=False):
     if update:
           dummy = myrandom.random()
     oldstate = myrandom.getstate()
     rand_num = myrandom.randint(0, 1000)
     myrandom.setstate(oldstate)
     return rand_num


This doesn't look like much, but it's actually an awful lot of work just to return a fixed, constant number! The PRNG used by Python is *very good*, which means it is also computationally quite expensive. Here's a cheaper way to get the same effect, using a mutable default argument to store the last result, then only call the PRNG when you actually need to:

def rand_int(update=False, seed=[None]):
     if update or seed[0] is None:
         seed[0] = random.randint(0, 1000)
     return seed[0]



-- 
Steven


More information about the Tutor mailing list