random 是平時開發過程中常用的一個模塊,該模塊實現了各種分布的偽隨機數生成器,以及和隨機數相關的各種實用函數。基本函數 random()
在區間 [0.0, 1.0)
內均勻生成隨機浮點數,是模塊中幾乎所有函數的基礎。
Python 使用 Mersenne Twister 作為核心生成器,由於完全確定性(對於給定的初始化條件,生成的隨機數序列完全確定,所以稱為“偽隨機數”),該模塊不適用於安全或加密用途。
由於入門語言是 C 語言,所以最開始用 Python 的時候還寫過
x = int(random() * a + b)
這樣的憨憨代碼(捂臉)。翻看文檔之后才發現標准庫中提供了很多便捷的函數,做個筆記記錄一下。
生成整數
random.randrange(stop)
/ random.randrange(start, stop[, step])
從 range(start, stop[, step])
中隨機選擇一個整數,參數的意義與 range()
完全一致,即左閉右開。
randrange(3) # 0, 1, 2
randrange(2, 5) # 2, 3, 4
randrange(2, 8, 2) # 2, 4, 6
random.randint(a, b)
最常用的隨機整數方法,返回整數 N 滿足 a <= N <= b。相當於 randrange(a, b+1)
。
生成實數(浮點數)
除了常用的均勻分布,random 模塊提供了很多種概率分布模式的隨機數,對應的分布方程以及參數與數學中的命名相對應。這里只簡單列出幾個比較常見的。
random.random()
均勻分布,生成 [0.0, 1.0) 之間的浮點數
random.uniform(a, b)
均勻分布,生成 a 到 b 之間的浮點數(包含端點),不需要保證 a <= b
random.expovariate(lambd)
指數分布,參數 lambd != 0
random.gammavariate(alpha, beta)
Gamma 分布,alpha > 0, beta > 0
random.gauss(mu, sigma)
/ random.normalvariate(mu, sigma)
正態分布(高斯分布),mu - 平均值,sigma - 標准差(>0)
- 兩者功能相同,前者速度略快,后者線程安全
序列/選擇
random.choice(seq)
從非空序列 seq 返回一個隨機元素。 如果 seq 為空,則引發 IndexError
random.choices(population, weights=None, *, cum_weights=None, k=1)
返回從 population 進行 k 次隨機抽樣結果的列表,即有重復(有放回)隨機抽樣。
可以指定每個元素對應的權重,如果未指定權重默認為等概率選擇
- weight 序列:指定相對權重
- cum_weights 序列:指定累積權重
- 例:相對權重
[10, 5, 30, 5]
相當於累積權重[10, 15, 45, 50]
- 例:相對權重
- 如果提供了權重序列,則它必須與 population 序列的長度相同
random.shuffle(x[, random])
將序列 x 隨機打亂位置。將改變 x 序列本身,而不是將新列表返回,因此傳入的 x 必須是可變列表(例如 list),如果傳入不可變對象(例如 tuple)會產生錯誤。random
是一個0參數函數,在 [0.0, 1.0) 中返回隨機浮點數,默認為 random()。
由於全排列數量為階乘增長,因此對於默認的隨機數生成器,如果輸入序列的長度超過 2080,那么大多數排列永遠不可能出現。
random.sample(population, k, *, counts=None)
不改變原序列 population,返回序列中不重復的 k 個元素的列表,即無重復隨機抽樣。要從一系列整數中選擇樣本,建議使用 range()
對象作為參數
序列中可以包含重復的元素,重復的元素可能會被同時選中(即完全按照給定列表選擇,不會進行去重)
- (Python >= 3.9)參數 counts 可以表示重復的元素。 例如,
sample(['red', 'blue'], counts=[4, 2], k=5)
等價於sample(['red', 'red', 'red', 'red', 'blue', 'blue'], k=5)
。
>>> choice(['win', 'lose', 'draw']) # 隨機選擇一個元素
'draw'
>>> choices(['red', 'black', 'green'], [18, 18, 2], k=6) # 加權抽取6個元素(有重復)
['red', 'green', 'black', 'black', 'red', 'black']
>>> deck = 'ace two three four'.split()
>>> shuffle(deck) # 打亂列表
>>> deck
['four', 'two', 'ace', 'three']
>>> sample([10, 20, 30, 40, 50], k=4) # 抽取4個隨機樣本(無重復)
[40, 10, 50, 30]
再現序列
有時需要重現偽隨機數的序列。
random.seed(a=None)
使用種子 a(NoneType, int, float, str, bytes 或 bytearray)初始化隨機數生成器,默認使用當前系統時間。通過重用一個種子值,可以在多次運行中再現相同的隨機序列(不考慮多線程情況)
random.getstate()
/ random.setstate(state)
捕獲/恢復生成器內部狀態,可以在單次運行中復現隨機序列
>>> status = random.getstate()
>>> random.random()
0.41528974297057974
>>> random.random()
0.5554723616955235
>>> random.setstate(status)
>>> random.random()
0.41528974297057974
>>> random.random()
0.5554723616955235