简体   繁体   中英

python random seeding is deterministic, but it shouldn't be

From the manual:

random.seed([x])

Initialize the basic random number generator. Optional argument x can be any hashable object. If x is omitted or None, current system time is used; current system time is also used to initialize the generator when the module is first imported. If randomness sources are provided by the operating system, they are used instead of the system time (see the os.urandom() function for details on availability).

If a hashable object is given, deterministic results are only assured when PYTHONHASHSEED is disabled.

user@MacBook:~$ python
Python 2.7.11 (default, Aug  6 2016, 02:11:50) 
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import random
>>> r = random.Random('somelongstring' * 40)
>>> r.randint(1, 1000)
332
>>> exit()

user@MacBook-Pro:~$ python
Python 2.7.11 (default, Aug  6 2016, 02:11:50) 
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import random
>>> r = random.Random('somelongstring' * 40)
>>> r.randint(1, 1000)
332
>>> 

The trouble is, i'm trying to get the same result everytime, but according to the manual and the PYTHONHASHSEED, i shoundn't be getting the same results every time. I've tried this on mac os, linux, python2.7 and pypy and they keep the same results over and over again.

The default value for PYTHONHASHSEED is to be disabled; there is no random hashing in Python 2 unless you explicitly enable it. It was deliberately kept optional in Python 2 to avoid breaking apps that relied on the hash being stable across Python processes, it was only made the default for Python 3.

If you were to enable it (with the -R command line switch or with the environment variable) then you'd indeed see a difference:

$ python2.7 -R -c "import random; random.seed('somelongstring' * 40); print random.randint(1, 1000)"
955
$ python2.7 -R -c "import random; random.seed('somelongstring' * 40); print random.randint(1, 1000)"
277

From the -R switch documentation:

Changing hash values affects the order in which keys are retrieved from a dict. Although Python has never made guarantees about this ordering (and it typically varies between 32-bit and 64-bit builds), enough real-world code implicitly relies on this non-guaranteed behavior that the randomization is disabled by default.

Python 3 also changed how str , bytes and bytearray objects are used; they inform the seed without using their hash.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM