我调用random.seed(234),然后调用random.randint(0,99)并收到92.当我再次重复此过程几次时,我收到86.当我第二次调用random.randint然后它返回92.我期待第一个值是86而不是92.为什么它是92?
完整的日志输出如下。我已经包含了所有这些内容,因为之前有一些行动可以解释看似错误的行为:
In [1]: import random
In [2]: import string
In [3]: string.letters
Out[3]: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
In [4]: string.ascii_letters
Out[4]: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
In [5]: string.printable
Out[5]: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
In [6]: len(string.printable)
Out[6]: 100
In [7]: [string.printable[random.randint(0,99)] for i in range(20)]
Out[7]:
['{',
'+',
'[',
'\r',
'R',
'Z',
'v',
'|',
'v',
'e',
'T',
'x',
'\\',
'}',
'0',
'>',
'V',
'\n',
'`',
'`']
In [8]: ''.join([string.printable[random.randint(0,99)] for i in range(20)])
Out[8]: '%Z\\%mx4Z53uUZIa5KHe*'
In [9]: ''.join([string.printable[random.randint(0,99)] for i in range(20)])
Out[9]: 'Fg\nDHW+oV?-9``}\x0by%xD'
In [10]: import os
In [11]: os.urandom(1)
Out[11]: '('
In [12]: os.urandom(1)
Out[12]: '8'
In [13]: os.urandom(1)
Out[13]: '\xb1'
In [14]: os.urandom(1)
Out[14]: ')'
In [15]: os.urandom(1)
Out[15]: '\x8c'
In [16]: os.urandom(1)
Out[16]: '^'
In [17]: os.urandom(1)
Out[17]: '{'
In [18]: os.urandom(1)
Out[18]: '\x8f'
In [19]: ''.join(os.urandom(10))
Out[19]: '{t\x8dR\x1d\x83\xef\xd6N\xbd'
In [20]: ''.join(os.urandom(10))
Out[20]: '\x96\\\xf6\xe3\xf4/\x1f\xc7\x90\x02'
In [21]: from random import SystemRandom
In [22]: crypt = SystemRandom()
In [23]: ''.join([string.printable[crypt.randrange(100)] for i in range(20)])
Out[23]: "WoDVH\r1!?1+djB'f<;nW"
In [24]: ''.join([string.printable[crypt.randrange(100)] for i in range(20)])
Out[24]: '\rf?zo`7^{Y_Zx^[SYw7c'
In [25]: ''.join([string.printable[crypt.randrange(100)] for i in range(20)])
Out[25]: "3k*uGVIP'~^{P*~bserk"
In [26]: ''.join([string.printable[crypt.randrange(100)] for i in range(20)])
Out[26]: '~lkM/a&#_F&D\n<sC&i\r\n'
In [27]: random.seed(234)
In [28]: random.randint(0,99)
Out[28]: 92
In [29]: random.seed(234)
In [30]: random.randint(0,99)
Out[30]: 86
In [31]: random.seed(234)
In [32]: random.randint(0,99)
Out[32]: 86
In [33]: random.seed(234)
In [34]: random.randint(0,99)
Out[34]: 86
In [35]: random.randint(0,99)
Out[35]: 92
In [36]: random.randint(0,99)
Out[36]: 48
In [37]: random.seed(234)
In [38]: random.randint(0,99)
Out[38]: 86
In [39]: import sys
In [40]: sys.version_info
Out[40]: sys.version_info(major=2, minor=7, micro=13, releaselevel='final', serial=0)
In [41]: sys.version
Out[41]: '2.7.13 (default, Dec 17 2016, 23:03:43) \n[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)]'
** 编辑,怪异:“相同”看似错误的行为重复 ** 在同一个终端窗口中,我关闭了之前的ipython会话。我做了一些命令行活动,然后我又打开了ipython。我做了一些不同的工作。然后我再试一次:
In [37]: import random
In [38]: random.seed(234)
In [39]: random.randint(0, 99)
Out[39]: 85
In [40]: random.randint(0, 99)
Out[40]: 50
In [41]: random.seed(234)
In [42]: random.randint(0, 99)
Out[42]: 86
In [43]: random.randint(0, 99)
Out[43]: 92
答案 0 :(得分:8)
这里发生的事情是,IPython系统中的某些东西正在使用@RequestMapping(value = "/images/{imageId}", method = RequestMethod.GET)
public ResponseEntity<byte[]> getEventImage(@PathVariable("imageId") String imageId) {
模块,因此消耗核心Mersenne Twister生成器提供的随机流中的数字。这意味着,如果您还使用random
模块,则只能看到流中数字的不可预测的子集,因为IPython会完成剩下的工作。
我可以通过在random
的调用之间随机点击<Enter>
键几次来重现您可靠地看到的效果(在Python 2和Python 3上)(尽管我实际上是#&# 39; m为了简单起见使用random.randint
。这是一个示例会话,在macOS 10.12.6上使用Python 3.6.2和IPython 6.2.0。
random.random
要检查我的假设,我通过将以下方法添加到In [1]: import random
In [2]: random.seed(234)
In [3]:
In [3]:
In [3]: random.random()
Out[3]: 0.8579160018299248
In [4]: random.random()
Out[4]: 0.5055065431394443
In [5]: random.seed(234)
In [6]: random.random()
Out[6]: 0.26476014305349627
In [7]: random.random()
Out[7]: 0.8579160018299248
In [8]: random.random()
Out[8]: 0.5055065431394443
类来攻击标准库中Random.random
文件中的random.py
方法:
Random
现在启动IPython,嘿presto!很多追溯。我不会完全重现这些追溯(他们很长),但是其中一个是尾声:
def random(self):
print("random being called")
import traceback; traceback.print_stack()
return super(Random, self).random()
正如您所看到的,IPython使用的prompt_toolkit
库使用随机模块来重新排列其任务(尽管最近根据CHANGELOG删除了此更改)。
如果您需要可靠的可重现的随机流,请创建一个明确的 File "/opt/local/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/IPython/terminal/interactiveshell.py", line 376, in prompt_for_code
pre_run=self.pre_prompt, reset_current_buffer=True)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/prompt_toolkit/interface.py", line 415, in run
self.eventloop.run(self.input, self.create_eventloop_callbacks())
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/prompt_toolkit/eventloop/posix.py", line 157, in run
random.shuffle(tasks)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/random.py", line 278, in shuffle
j = randbelow(i+1)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/random.py", line 250, in _randbelow
r = random()
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/random.py", line 98, in random
import traceback; traceback.print_stack()
实例并使用它:
random.Random
答案 1 :(得分:-1)
我的Python 2.7.5无法重现相同的行为,但文档 (https://docs.python.org/2/library/random.html)说
如果a不是None或int或long,则使用hash(a)代替。 请注意,某些类型的哈希值是不确定的 PYTHONHASHSEED已启用。
我会(只是意见)说它可能是由哈希函数的非确定性行为引起的。您的PYTHONHASHSEED已启用吗?