2

I notice that if I seed Python's PRNG with a tuple, I get different results each time I do it. That is, the Python 3.4 program:

import random
seed1 = ('Foo', 'Bar')
random.seed(seed1)
print(random.random())

prints a different number each time it is run. Is this because the seed taken is the id of the tuple seed1 which is different each time?

What is the best way to use a tuple as a seed to the PRNG so that I get repeatable results? Is it simply random.seed(str(seed1))?

xnx
  • 24,509
  • 11
  • 70
  • 109
  • So you want the same result each time you call random as opposed to a random result? – kylieCatt May 12 '15 at 14:24
  • @IanAuld, not exactly: I want the same output every time I run the above program; that is, I want Python to seed its Mersenne Twister with the same integer value generated from a given tuple. – xnx May 12 '15 at 14:26
  • Perhaps this will be of some help: http://stackoverflow.com/questions/9023660/how-to-generate-a-repeatable-random-number-sequence – kylieCatt May 12 '15 at 14:28

2 Answers2

2

From a previous question:

For Python 3.3+, as @gnibbler pointed out, hash() is randomized between runs. It will work for a single run, but almost definitely won't work across runs of your program (pulling from the text file you mentioned).

So using python 2.x, running hash('Foo', 'Bar') will generally return the same result on the same computer each time which gives you the same initial seed. On python 3.3+ running hash against your tuple gives you a unique value each time.

If you want to have a consistent result with python 3.3+ look into hashlib. For example:

import hashlib
import random

seed1 = ('Foo', 'Bar')
text  = u''.join(seed1).encode('utf-8')
sha   = hashlib.sha1(text)
random.seed(sha.hexdigest())
print(sha.hexdigest())
print(random.random())

> python3 random2.py 
eb8fc41f9d9ae5855c4d801355075e4ccfb22808
0.738130097774164
> python3 random2.py 
eb8fc41f9d9ae5855c4d801355075e4ccfb22808
0.738130097774164

> python2 random2.py 
eb8fc41f9d9ae5855c4d801355075e4ccfb22808
0.628422839243
> python2 random2.py 
eb8fc41f9d9ae5855c4d801355075e4ccfb22808
0.628422839243

i.e. you'll have a consistent seed, but since the random modules differ in their implementation you still get a different random number.

Community
  • 1
  • 1
Hooked
  • 84,485
  • 43
  • 192
  • 261
  • Thanks: I don't mind if it isn't stable across Python 2 / Python 3.4, but there's something I don't understand: `random.seed(sha.hexdigest())` is sending a `str` to `random.seed`: how come the hash generated from this `str` isn't randomized in the way the docs describe for Python 3.3+? – xnx May 12 '15 at 15:33
  • 1
    @xnx I wish I had a better answer (this is a good question IMHO). A hint lies in the help of each function across versions. In python3 it states "For version 2 (the default), all of the bits are used if *a* is a str, bytes, or bytearray. For version 1, the hash() of *a* is used instead." – Hooked May 12 '15 at 16:15
0

Interesting.

If you do this:

def repeatable_random(seed):
    random.seed(seed)
    while True:
        yield random.random()

for i, v in zip(range(20), repeatable_random(('Foo', 'Bar'))):
    print((i,v))

You get different values for the random series each time you run it.

If you do this:

def repeatable_random(seed):
    random.seed(repr(seed))      # Note 'repr' here
    while True:
        yield random.random()

for i, v in zip(range(20), repeatable_random(('Foo', 'Bar'))):
    print((i,v))

It is the same series 1=>n on different run of the Python interpreter.

dawg
  • 98,345
  • 23
  • 131
  • 206