你真的用好了Python的random模塊嗎?


random模塊


用於生成偽隨機數
源碼位置: Lib/random.py(看看就好,千萬別隨便修改)

真正意義上的隨機數(或者隨機事件)在某次產生過程中是按照實驗過程中表現的分布概率隨機產生的,其結果是不可預測的,是不可見的。而計算機中的隨機函數是按照一定算法模擬產生的,其結果是確定的,是可見的。我們可以這樣認為這個可預見的結果其出現的概率是100%。所以用計算機隨機函數所產生的“隨機數”並不隨機,是偽隨機數。

  1. 計算機的偽隨機數是由隨機種子根據一定的計算方法計算出來的數值。所以,只要計算方法一定,隨機種子一定,那么產生的隨機數就是固定的。
  2. 只要用戶或第三方不設置隨機種子,那么在默認情況下隨機種子來自系統時鍾。

Python的這個庫在底層使用通用的算法,經過長久的考驗,可靠性沒得說,但絕對不能用於密碼相關的功能。

一、基本方法

random.seed(a=None, version=2)
初始化偽隨機數生成器。如果未提供a或者a=None,則使用系統時間為種子。如果a是一個整數,則作為種子。

random.getstate()
返回一個當前生成器的內部狀態的對象

random.setstate(state)
傳入一個先前利用getstate方法獲得的狀態對象,使得生成器恢復到這個狀態。

random.getrandbits(k)
返回一個不大於K位的Python整數(十進制),比如k=10,則結果在0~2^10之間的整數。

二、針對整數的方法

random.randrange(stop)
random.randrange(start, stop[, step])
等同於choice(range(start, stop, step)),但並不實際創建range對象。

random.randint(a, b)
返回一個a <= N <= b的隨機整數N。等同於 randrange(a, b+1)

三、針對序列類結構的方法

random.choice(seq)
從非空序列seq中隨機選取一個元素。如果seq為空則彈出 IndexError異常。

random.choices(population, weights=None, *, cum_weights=None, k=1)
3.6版本新增。從population集群中隨機抽取K個元素。weights是相對權重列表,cum_weights是累計權重,兩個參數不能同時存在。

random.shuffle(x[, random])
隨機打亂序列x內元素的排列順序。只能針對可變的序列,對於不可變序列,請使用下面的sample()方法。

random.sample(population, k)
從population樣本或集合中隨機抽取K個不重復的元素形成新的序列。常用於不重復的隨機抽樣。返回的是一個新的序列,不會破壞原有序列。要從一個整數區間隨機抽取一定數量的整數,請使用sample(range(10000000), k=60)類似的方法,這非常有效和節省空間。如果k大於population的長度,則彈出ValueError異常。

四、真值分布

random模塊最高端的功能其實在這里。

random.random()
返回一個介於左閉右開[0.0, 1.0)區間的浮點數

random.uniform(a, b)
返回一個介於a和b之間的浮點數。如果a>b,則是b到a之間的浮點數。這里的a和b都有可能出現在結果中。

random.triangular(low, high, mode)
返回一個low <= N <=high的三角形分布的隨機數。參數mode指明眾數出現位置。

random.betavariate(alpha, beta)
β分布。返回的結果在0~1之間

random.expovariate(lambd)
指數分布

random.gammavariate(alpha, beta)
伽馬分布

random.gauss(mu, sigma)
高斯分布

random.lognormvariate(mu, sigma)
對數正態分布

random.normalvariate(mu, sigma)
正態分布

random.vonmisesvariate(mu, kappa)
卡帕分布

random.paretovariate(alpha)
帕累托分布

random.weibullvariate(alpha, beta)

五、可選擇的生成器

class random.SystemRandom([seed])
使用 os.urandom() 方法生成隨機數的類,由操作系統提供源碼,不一定所有系統都支持

六、典型的例子

>>> random()                             # 隨機浮點數:  0.0 <= x < 1.0
0.37444887175646646

>>> uniform(2.5, 10.0)                   # 隨機浮點數:  2.5 <= x < 10.0
3.1800146073117523


>>> randrange(10)                        # 0-9的整數:
7

>>> randrange(0, 101, 2)                 # 0-100的偶數
26

>>> choice(['win', 'lose', 'draw'])      # 從序列隨機選擇一個元素
'draw'

>>> deck = 'ace two three four'.split()
>>> shuffle(deck)                        # 對序列進行洗牌,改變原序列
>>> deck
['four', 'two', 'ace', 'three']

>>> sample([10, 20, 30, 40, 50], k=4)    # 不改變原序列的抽取指定數目樣本,並生成新序列
[40, 10, 50, 30]


>>> # 6次旋轉紅黑綠輪盤(帶權重可重復的取樣),不破壞原序列
>>> choices(['red', 'black', 'green'], [18, 18, 2], k=6)
['red', 'green', 'black', 'black', 'red', 'black']

>>> # 德州撲克計算概率Deal 20 cards without replacement from a deck of 52 playing cards
>>> # and determine the proportion of cards with a ten-value
>>> # (a ten, jack, queen, or king).
>>> deck = collections.Counter(tens=16, low_cards=36)
>>> seen = sample(list(deck.elements()), k=20)
>>> seen.count('tens') / 20
0.15

>>> # 模擬概率Estimate the probability of getting 5 or more heads from 7 spins
>>> # of a biased coin that settles on heads 60% of the time.
>>> trial = lambda: choices('HT', cum_weights=(0.60, 1.00), k=7).count('H') >= 5
>>> sum(trial() for i in range(10000)) / 10000
0.4169

>>> # Probability of the median of 5 samples being in middle two quartiles
>>> trial = lambda : 2500 <= sorted(choices(range(10000), k=5))[2]  < 7500
>>> sum(trial() for i in range(10000)) / 10000
0.7958

下面是生成一個包含大寫字母A-Z和數字0-9的隨機4位驗證碼的程序

import random
 
checkcode = ''
for i in range(4):
    current = random.randrange(0,4)
    if current != i:
        temp = chr(random.randint(65,90))
    else:
        temp = random.randint(0,9)
    checkcode += str(temp)
print(checkcode)

下面是生成指定長度字母數字隨機序列的代碼:

#!/usr/bin/env python
# -*- coding:utf-8 -*-


import random, string


def gen_random_string(length):
    # 數字的個數隨機產生
    num_of_numeric = random.randint(1,length-1)
    # 剩下的都是字母
    num_of_letter = length - num_of_numeric
    # 隨機生成數字
    numerics = [random.choice(string.digits) for i in range(num_of_numeric)]
    # 隨機生成字母
    letters = [random.choice(string.ascii_letters) for i in range(num_of_letter)]
    # 結合兩者
    all_chars = numerics + letters
    # 洗牌
    random.shuffle(all_chars)
    # 生成最終字符串
    result = ''.join([i for i in all_chars])
    return result

if __name__ == '__main__':
    print(gen_random_string(64))


免責聲明!

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



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