【Python】详解 random 模块

目录

一、绪论

二、说明

2.1 random.random() —— 获取伪随机数

2.2 random.seed() —— 记录与复现 (随机数种子)

2.3 random.randrange() / random.randint() —— 指定范围内生成伪随机数

2.4 random.choice() / random.choices() —— 对序列随机抽样

2.5 random.shuffle() —— 随机打乱序列顺序

2.6 random.sample() —— 对序列无重复随机抽样

2.7 各类概率分布


一、绪论

给定相同的输入,大多数计算机程序每次都会生成相同的输出,它们因此被称作确定性的。然而,有时候我们并不需要这样的确定性,而是希望得到不可预知的随机结果。让程序具备真正意义上的非确定性并不容易,但还是是有办法使它至少看起来是不确定的。 其中之一是使用生成伪随机数 (pseudorandom) 的算法。伪随机数不是真正的随机数, 因为它们由一个确定性的计算生成,但是仅看其生成的数字,不可能将它们和随机生成的相区分开。

random 模块,顾名思义是与随机数操作相关的模块,它实现了各种分布的伪随机数生成器。但因为结果的完全确定性,它不适用于所有情况,特别是完全不适用于加密。以下将介绍一些常用功能。


二、说明

2.1 random.random() —— 获取伪随机数

random.random() 方法无需参数,调用后直接返回一个 [0.0, 1.0) 范围内的 float 型伪随机数,例如:

import random        # 导入 random 模块

>>> random.random()  # 获取一个伪随机数
0.3927174258393834

>>> random.random()  # 再获取一个伪随机数
0.5254320253344416

2.2 random.seed() —— 记录与复现 (随机数种子)

random.seed(a=None) 方法用于初始化随机数生成器,即生成或改变“随机数种子”。

若参数 a 被省略或为 None,则使用当前系统时间;若操作系统提供随机源,则使用操作系统随机源。

若参数 a 是 int 型数字,则直接使用。(现在 a 也可以是 float、string、bytes 等类型)

调用 random.random() 生成伪随机数时,每次生成的数都是随机的。但若预先调用 random.seed(a) 设好随机数种子后,再用 random.random() 将得到同一个伪随机数,从而确保“可复现”。例如:

>>> random.random()  # 不使用随机数种子, 获取未知随机数
0.9871512831697422
>>> random.random()  # 不使用随机数种子, 获取未知随机数
0.1582084156493

>>> random.seed(1)   # 设置一个随机数种子 1
>>> random.random()  # 获取随机数种子 1 的已知随机数
0.13436424411240122

>>> random.random()  # 不使用随机数种子, 仍获取未知随机数
0.8474337369372327

>>> random.seed(1)   # 再使用设好的随机数种子 1, 得到已知随机数 
>>> random.random()
0.13436424411240122

上述用法显而易见,当然,还存在一些不常见的用法:

>>> random.seed('s')    # 使用 string 设置 seed
>>> random.random()
0.47702766547742415

>>> random.seed(b'ss')  # 使用 bytes 设置 seed
>>> random.random()
0.8708725367892596

>>> random.seed(1.2)    # 使用 float 设置 seed
>>> random.random()
0.24751702373640583

>>> random.seed('s')    # string 型复现
>>> random.random()
0.47702766547742415

>>> random.seed(b'ss')  # bytes 型复现
>>> random.random()
0.8708725367892596

>>> random.seed(1.2)    # float型复现
>>> random.random()
0.24751702373640583

注意,只要没有多个线程运行,通过重新使用随机数种子值就能复现伪随机数。

2.3 random.randrange() / random.randint() —— 指定范围内生成伪随机数

random.randrange(stop) 相当于在 range(stop) 中随机输出一个 int 型数字。

random.randrange(start, stop[, step]) 同理相当于在 range(start, stop[, step]) 中随机输出一个 int 型数字。

上述方法类似于 range() 的位置参数匹配模式,而不应使用关键字参数,且实际上并未构建 range 对象。

>>> random.randrange(6)       # 指定 stop 参数测试
0
>>> random.randrange(6)
3

>>> random.randrange(1,6)     # 指定 start, stop 参数测试
5
>>> random.randrange(1,6)
4

>>> random.randrange(1,6,3)   # 指定 start, stop, step 参数测试
4
>>> random.randrange(1,6,3)
1

random.randint(a, b) 返回 [a, b] 范围内的随机 int 数,相当于随机取 range(a, b+1) 中的一数输出。

>>> random.randint(1,6)
1
>>> random.randint(1,6)
6

2.4 random.choice() / random.choices() —— 对序列随机抽样

random.choice(seq) 从非空序列 seq 返回一个随机元素。若 seq 为空将抛出 IndexError 。

>>> random.choice(['a', 'k', '4', '7', 6])  # seq 为 list 
'k'
>>> random.choice(['a', 'k', '4', '7', 6])
6

>>> random.choice(('m', '4', 'a', '1', 1))  # seq 为 tuple
'm'
>>> random.choice(('m', '4', 'a', '1', 1))
'a'

>>> random.choice('csgo')  # seq 为 string
'c'
>>> random.choice('csgo')
'g'

random.choices(populationweights=None*cum_weights=Nonek=1) 从序列 population 随机返回长度为 k 的元素 list。 若 population 为空将抛出 IndexError 。

注意指定输出长度 k 要使用关键字参数

>>> random.choices(['a', 'k', '4', '7', 6])  # 默认返回长度 k=1 的 list
['a']
>>> random.choices(['a', 'k', '4', '7', 6])
[6]
>>> random.choices(['a', 'k', '4', '7', 6], k=2)  # 若要指定返回 list 长度需用关键字参数
['4', 'a']
>>> random.choices(['a', 'k', '4', '7', 6], k=2)
['a', 'k']

若指定相对权重序列 weight,则根据相对权重选择;若指定累积权重序列 cum_weights,则根据累积权重选择。

权重序列必须与序列 population 等长,因为它与序列 population 各元素输出概率成正比。例如,相对权重 [10, 5, 30, 5] 相当于百分制的累积权重 [10, 15, 45, 50]。在内部,相对权重在选择前会转换为累积权重,因此直接提供累积权重可节省计算量。

注意指定权重需用关键字参数;若不指定任何权重,则等概率选择。 

>>> random.choices(['a', 'k', '4', '7', 6], cum_weights=[1,2,3,4,5],k=2)
['a', '4']
>>> random.choices(['a', 'k', '4', '7', 6], weights=[1,2,3,4,5],k=2)
['k', '4']
>>> random.choices(['a', 'k', '4', '7', 6], weights=[0.1,0.2,0.3,0.4,0.5],k=2)
[6, 6]
>>> random.choices(['a', 'k', '4', '7', 6], cum_weights=[10,20,30,40,0],k=2)
['7', '7']

2.5 random.shuffle() —— 随机打乱序列顺序

random.shuffle(x[, random]) 打乱序列 x 的元素位置。注意,这是就地 (in-place) 重洗数据,以节省空间。

>>> _list = ['a', 'k', '4', '7', 6]  # 以 list 为例
>>> random.shuffle(_list)
>>> _list
[6, 'a', '4', 'k', '7']

2.6 random.sample() —— 对序列无重复随机抽样

random.sample(populationk) 从序列或集合 population 中返回长度为 k 的 list,而不会改变原序列或集合 population,常用于无重复随机抽样。换言之,每次从 population 中选中用于输出的元素不会被再次选到。

>>> x = [1,1,2,2,3,3,4,4]
>>> random.sample(x,4)
[2, 3, 4, 3]
>>> random.sample(x,8)
[2, 1, 4, 1, 2, 3, 4, 3]

2.7 各类概率分布

random.uniform(a, b) 返回一个随机 float 数 N 。若 a ≤ b,则 a ≤ N ≤ b;若 a > b 时,则 b ≤ N ≤ a 。

>>> random.uniform(1,6)
2.360764594102883
>>> random.uniform(6,1)
1.1694993454817864

random.triangular(lowhighmode) 返回一个随机 float 数 N,满足 low ≤ N ≤ high,并在这些边界间使用指定的 mode 。

默认边界 low=0,high=1。mode 参数默认为边界间的中点,给出对称分布。

>>> random.triangular()
0.7901206686668583
>>> random.triangular(1,3)
2.2824148437047245

random.betavariate(alphabeta) 按 beta 分布返回 float 数,范围 0 ~ 1,要求参数 alpha>0,beta>0 。

>>> random.betavariate(1,2)
0.0002116366994341509
>>> random.betavariate(6,7)
0.4745896776730147

random.expovariate(lambd) 按指数分布返回 float 数,参数 lambd 是 1.0 除以所需的平均值,应为非零数。

(该参数本应命名为 “lambda” ,但这是 Python 中的保留字)

若 lambd 为正,则返回值范围为 0 ~ +∞;若 lambd 为负,则返回值范围为 -∞ ~ 0 。

>>> random.expovariate(1)
0.1350680972867813
>>> random.expovariate(-1)
-2.05439953632068

random.gammavariate(alphabeta) 按 gamma 分布 (不是 gamma 函数) 返回 float 数,要求参数 alpha>0,beta>0。

random.gauss(mu, sigma按高斯 (gauss) 分布返回 float 数,mu 是平均值,sigma 是标准差。

这比 random.normalvariate() 略快。

random.lognorrmvariate(musigma按对数正态分布返回 float 数。mu 是平均值,可为任意值;sigma 是标准差,须大于0。若采用该分布的自然对数,将得到一个正态分布。

random.normalvariate(musigma按正态分布返回 float 数,mu 是平均值,sigma 是标准差。

random.vonmisesvariate(mukappa) 按冯·米塞斯 (von Mises) 分布返回 float 数, mu 是平均角度,以弧度表示,介于 0~ 2π 之间;kappa 是浓度参数,必须大于等于 0。 若 kappa 等于 0,则该分布在 0~ 2π 的范围内减小到均匀的随机角度。

random.paretovariate(alpha按帕累托分布返回 float 数,alpha 是形状参数.

random.weibullvariate(alphabeta按威布尔分布返回 float 数,alpha 是比例参数,beta 是形状参数。


参考文献:

《Think Python》

https://docs.python.org/zh-cn/3.6/library/random.html?highlight=random%20模块#module-random

https://www.runoob.com/python/func-number-seed.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章