Python | random 模塊:Python 中如何生成隨機數和隨機抽樣?


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

參考文獻

Python 3.9 文檔 > 標准庫 > 數字和數學模塊


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM