Ari*_*ide 7 python shuffle python-2.7 python-3.x random-seed
我正在编写一个兼容Python 2.7和3.5的程序.它的某些部分依赖于随机过程.我的单元测试使用任意种子,这导致执行和语言相同的结果......除了使用的代码random.shuffle.
Python 2.7中的示例:
In[]: import random
random.seed(42)
print(random.random())
l = list(range(20))
random.shuffle(l)
print(l)
Out[]: 0.639426798458
[6, 8, 9, 15, 7, 3, 17, 14, 11, 16, 2, 19, 18, 1, 13, 10, 12, 4, 5, 0]
Run Code Online (Sandbox Code Playgroud)
Python 3.5中的相同输入:
In []: import random
random.seed(42)
print(random.random())
l = list(range(20))
random.shuffle(l)
print(l)
Out[]: 0.6394267984578837
[3, 5, 2, 15, 9, 12, 16, 19, 6, 13, 18, 14, 10, 1, 11, 4, 17, 7, 8, 0]
Run Code Online (Sandbox Code Playgroud)
注意,伪随机数是相同的,但是混洗列表是不同的.正如预期的那样,重新执行单元格不会改变它们各自的输出.
我怎么能为两个版本的Python编写相同的测试代码?
Mar*_*ers 16
在Python 3.2中,随机模块进行了一些重构,以使输出在架构之间保持一致(给定相同的种子),请参阅问题#7889.该shuffle()方法转为使用Random._randbelow().
但是,该_randbelow()方法也进行了调整,因此仅仅复制3.5版本shuffle()还不足以解决这个问题.
也就是说,如果你传入自己的random()函数,Python 3.5中的实现与2.7版本相同,因此可以绕过这个限制:
random.shuffle(l, random.random)
Run Code Online (Sandbox Code Playgroud)
但请注意,与现在相比,#7889试图解决的旧32位与64位架构差异.
忽略多个优化和特殊情况,如果包含_randbelow()3.5版本,则可以向后移植为:
import random
import sys
if sys.version_info >= (3, 2):
newshuffle = random.shuffle
else:
try:
xrange
except NameError:
xrange = range
def newshuffle(x):
def _randbelow(n):
"Return a random int in the range [0,n). Raises ValueError if n==0."
getrandbits = random.getrandbits
k = n.bit_length() # don't use (n-1) here because n can be 1
r = getrandbits(k) # 0 <= r < 2**k
while r >= n:
r = getrandbits(k)
return r
for i in xrange(len(x) - 1, 0, -1):
# pick an element in x[:i+1] with which to exchange x[i]
j = _randbelow(i+1)
x[i], x[j] = x[j], x[i]
Run Code Online (Sandbox Code Playgroud)
它在2.7和3.5上给你相同的输出:
>>> random.seed(42)
>>> print(random.random())
0.639426798458
>>> l = list(range(20))
>>> newshuffle(l)
>>> print(l)
[3, 5, 2, 15, 9, 12, 16, 19, 6, 13, 18, 14, 10, 1, 11, 4, 17, 7, 8, 0]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1111 次 |
| 最近记录: |