mercredi 5 août 2020

Why does wrapping the random method of random.Random seem to affect the RNG?

I tried to log calls to random() by putting a wrapper around it to print stuff. Surprisingly I noticed that I started getting different random values. I have created a small example to demonstrate the behavior:

Script main.py:

import random

def not_wrapped(seed):
    """ not wrapped """
    gen = random.Random()
    gen.seed(seed)

    # def wrappy(func):
    #     return lambda: func()
    # gen.random = wrappy(gen.random)

    gen.randint(1, 1)
    return gen.getstate()

def wrapped(seed):
    """ wrapped """
    gen = random.Random()
    gen.seed(seed)

    def wrappy(func):
        return lambda: func()
    gen.random = wrappy(gen.random)

    gen.randint(1, 1)
    return gen.getstate()

for s in range(20):
    print(s, not_wrapped(s) == wrapped(s))

Output of python3.7.5 main.py (same as python 3.6.9)

0 True
1 False
2 False
3 False
4 False
5 True
6 False
7 False
8 False
9 False
10 True
11 False
12 False
13 False
14 False
15 True
16 False
17 True
18 False
19 True

So as you see the state of the Random instance gen is different and it depends on if I wrap gen.random in wrappy or not.

If I call randint() twice the test will fail for all seeds 0-19. For Python 2.7.17 the wrapped and not_wrapped functions returns the same random value every time (prints True for every seed).

Does anyone know what is going on?

Python 3.6 online example: http://tpcg.io/inbKc8hK

On Python 3.8.2 on this online repl, the problem does not show: https://repl.it/@DavidMoberg/ExemplaryTeemingDos




Aucun commentaire:

Enregistrer un commentaire