【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

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