random模块基于Mersenne Twister算法提供了一个快速伪随机数生成器,原先开发这个生成器是为了向蒙特卡洛模拟生成输出,Mersenne Twister算法会生成大周期近均匀分布的数,因此适用于大量不同类型的应用
继承树
_random.Random(builtins.object)
Random
SystemRandom
生成随机数
random()
random(),random() -> x in the interval [0, 1)
random()函数从所生成的序列返回下一个随机的浮点值,返回的所有值都落在 0≤n<1.0 区间内
import random
for i in range(10):
print('%.3f' % random.random(), end=' ')
# 0.905 0.541 0.897 0.384 0.732 0.419 0.949 0.500 0.365 0.232
uniform()
uniform(a, b),Get a random number in the range [a, b) or [a, b] depending on rounding
使用uniform()函数会生成一个指定区间的数,在uniform()函数中传入最大值和最小值,uniform()会使用公式来调整random()的返回值
公式:min + ( max - min ) * random()
import random
for i in range(10):
print('%.1f' % random.uniform(1, 2), end=' ')
# 53.660 68.371 35.115 61.124 5.931 81.609 89.923 3.352 41.802 41.302
for i in range(10):
print('%.1f' % random.uniform(1, 2), end=' ')
# 1.0 1.5 1.8 1.7 1.7 2.0 1.0 1.4 1.2 1.1
指定种子
seed()
seed(a=None, version=2),Initialize internal state from hashable object
None or no argument seeds from current time or from an operating system specific randomness source if available
If *a* is an int, all bits are used
For version 2 (the default), all of the bits are used if a is a str, bytes, or bytearray. For version 1 (provided for reproducing random sequences from older versions of Python), the algorithm for str and bytes generates a narrower range of seeds
每一次调用random()函数都会生成不同的值,并且在一个非常大的周期之后数字才会重复
seed()函数可以用来初始化伪随机数生成器,使它生成一个期望的值集
import random
# 参数为任意可哈希类型的对象
random.seed((1))
for i in range(10):
print('%.3f' % random.uniform(1, 100), end=' ')
# 多次运行后其结果相同
# 14.302 84.896 76.614 26.252 50.048 45.500 65.508 79.084 10.292 3.806
# 14.302 84.896 76.614 26.252 50.048 45.500 65.508 79.084 10.292 3.806
print('\n')
for i in range(10):
print('%.3f' % random.uniform(1, 100), end=' ')
# 83.741 43.844 76.466 1.208 45.093 72.432 23.647 94.582 90.241 4.028
# 83.741 43.844 76.466 1.208 45.093 72.432 23.647 94.582 90.241 4.028
种子(seed)值会控制由公式生成的第一个值,该公式可用来生成伪随机数,由于该公式是确定的,所以改变种子后便设置了将要生成的整个序列,seed()参数可以是任意散列(可哈希)对象,默认使用一个平台特定的随机源(如果有的话),如果没有随机源,则使用当前时间
保存状态
random()使用的伪随机数算法的内部状态可以保存,并用于控制后续生成的随机数,使用getstate()会返回数据的实现细节,以后可借助setstate()函数并利用getstate()返回的数据重新初始化伪随机数生成器
getstate()
getstate(),Return internal state; can be passed to setstate() later
setstate()
setstate(state),Restore internal state from object returned by getstate()
import random
for i in range(10):
print('%.3f' % random.random(), end=' ')
print('\n')
# 0.416 0.970 0.960 0.600 0.121 0.006 0.813 0.834 0.145 0.757
# 保存初始化状态
state = random.getstate()
for i in range(10):
print('%.3f' % random.random(), end=' ')
print('\n')
for i in range(10):
print('%.3f' % random.random(), end=' ')
print('\n')
for i in range(10):
print('%.3f' % random.random(), end=' ')
print('\n')
# 0.754 0.289 0.327 0.914 0.482 0.084 0.701 0.393 0.808 0.811
# 0.535 0.038 0.209 0.128 0.124 0.102 0.108 0.204 0.668 0.201
# 0.826 0.191 0.248 0.015 0.725 0.830 0.468 0.587 0.581 0.421
# 重新设置初始化状态
random.setstate(state)
for i in range(10):
print('%.3f' % random.random(), end=' ')
print('\n')
for i in range(10):
print('%.3f' % random.random(), end=' ')
print('\n')
for i in range(10):
print('%.3f' % random.random(), end=' ')
print('\n')
# 0.754 0.289 0.327 0.914 0.482 0.084 0.701 0.393 0.808 0.811
# 0.535 0.038 0.209 0.128 0.124 0.102 0.108 0.204 0.668 0.201
# 0.826 0.191 0.248 0.015 0.725 0.830 0.468 0.587 0.581 0.421
# 再次重新初始化状态
random.setstate(state)
for i in range(10):
print('%.3f' % random.random(), end=' ')
print('\n')
for i in range(10):
print('%.3f' % random.random(), end=' ')
print('\n')
for i in range(10):
print('%.3f' % random.random(), end=' ')
print('\n')
# 0.754 0.289 0.327 0.914 0.482 0.084 0.701 0.393 0.808 0.811
# 0.535 0.038 0.209 0.128 0.124 0.102 0.108 0.204 0.668 0.201
# 0.826 0.191 0.248 0.015 0.725 0.830 0.468 0.587 0.581 0.421
随机整数
randint()
randint(a, b),Return random integer in range [a, b], including both end points
randint()的参数是值的闭区间的两端,可以为负数,第一个参数的值要小于第二个参数
randrange()
randrange(start, stop=None, step=1, _int=<class ‘int’>),Choose a random item from range(start, stop[, step])
This fixes the problem with randint() which includes the endpoint; in Python this is usually not what you want
randrange()支持步长参数,所以完全等价于range(start, stop, step)选择一个随机值,但randrange()更加高效,因为它并不真正构建区间
import random
for i in range(5):
print(random.randint(1, 4), end=' ')
print('\n')
# 结果包含端点值
# 1 1 1 4 2
for i in range(5):
print(random.randrange(1, 4), end=' ')
# 结果不包含端点值
# 3 2 2 1 3
选择随机元素
choice()
choice(seq),Choose a random element from a non-empty sequence
choice()函数可以从一个序列中随机选择
import random
# 模拟抛硬币
outcomes = {'正面' : 0, '反面' : 0}
sides = list(outcomes.keys())
for i in range(10000):
# 随机选择字典中的一个key对其进行加一,表示选择了硬币的哪一面
outcomes[random.choice(sides)] += 1
print('正面', outcomes['正面'])
print('反面', outcomes['反面'])
# 正面 5095
# 反面 4905
洗牌
shuffle()
shuffle(x, random=None),Shuffle list x in place, and return None
Optional argument random is a 0-argument function returning a random float in [0.0, 1.0); if it is the default None, the standard random.random will be used
将一个列表中的值打乱,即洗牌
import random
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9]
random.shuffle(lst)
print(lst)
# [9, 7, 4, 3, 2, 8, 1, 5, 6]
采样
sample()
sample(population, k),Chooses k unique random elements from a population sequence or set
sample()函数可以生成无重复值的样本,并且不会修改输入序列
sample()函数的生成结果集算法会考虑输入的规模和请求的样本,从而尽可能高效地生成结果
import random
lst = [i for i in range(1, 21)]
print(lst)
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
# 随机抽取列表中的10个值
print(random.sample(lst, 10))
# [15, 4, 17, 5, 20, 9, 7, 10, 13, 3]
# 取值的个数超过原列表范围
print(random.sample(lst, 21))
# ValueError: Sample larger than population or is negative
多个并发生成器
random模块下包含一个Random类以管理多个随机数生成器的内部状态,上面的函数均可以作为Random实例的方法得到,并且每个实例都可以被单独初始化和使用,不会干扰其他实例的返回值
import random
r1 = random.Random()
r2 = random.Random()
for i in range(5):
print('%.3f' % r1.random(), end=' ')
print('\n')
# 0.937 0.973 0.715 0.231 0.355
for i in range(5):
print('%.3f' % r2.random(), end=' ')
print('\n')
# 0.292 0.933 0.125 0.387 0.047
# 设置相同的种子
r1.seed(1)
r2.seed(1)
for i in range(5):
print('%.3f' % r1.random(), end=' ')
print('\n')
# 0.134 0.847 0.764 0.255 0.495
for i in range(5):
print('%.3f' % r2.random(), end=' ')
print('\n')
# 0.134 0.847 0.764 0.255 0.495
SystemRandom
有些操纵系统提供了一个随机数生成器,可以访问更多能引入生成器的信息源,random通过SystemRandom类提供该特性,SystemRandom类与Random类的API相同,不过使用os.urandom()生成值,该值会构成所有其他算法的基础
SystemRandom产生的序列是不可再生的,因为其随机性来自系统,而非软件状态,即seed()和setstate()不会起作用
import random
r1 = random.SystemRandom()
r2 = random.SystemRandom()
for i in range(5):
print(r1.randint(1, 100), end=' ')
print('\n')
# 83 31 44 12 56
for i in range(5):
print(r1.randint(1, 100), end=' ')
print('\n')
# 70 76 55 90 82
# 设置相同的种子值
r1.seed(1)
r2.seed(1)
for i in range(5):
print(r1.randint(1, 100), end=' ')
print('\n')
# 93 14 78 79 38
for i in range(5):
print(r1.randint(1, 100), end=' ')
print('\n')
# 36 1 44 20 41
非均匀分布
random()生成的值为均匀分布
random模块中包含一些函数以生成非均匀分布的值,可实现的分布:
- 正态分布
- 近似分布
- 指数分布
- 角分布
- 大小分布