溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Python隨機值怎么實現(xiàn)

發(fā)布時間:2022-10-11 17:24:15 來源:億速云 閱讀:125 作者:iii 欄目:web開發(fā)

本文小編為大家詳細介紹“Python隨機值怎么實現(xiàn)”,內(nèi)容詳細,步驟清晰,細節(jié)處理妥當,希望這篇“Python隨機值怎么實現(xiàn)”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識吧。

介紹

生成隨機值的能力是一項重要的編程技能。即使你不是每天都需要它們,隨機值仍然會出現(xiàn)在數(shù)量驚人的地方。當然,對于許多人來說,當他們想到隨機值時,首先想到的是與游戲相關(guān)的用例,如洗牌、擲骰子和老虎機。

然而,隨機值還有許多其他用途。這些包括:

  • 生成安全密碼或密碼重置 URL。

  • 創(chuàng)建用于測試用例或代碼演示的示例數(shù)據(jù)。

  • 清理個人身份信息 (PII) 數(shù)據(jù)以準備數(shù)據(jù)以供分析。

與許多其他重要的編程任務(wù)一樣,Python編程語言具有設(shè)計良好、一致的支持,可以生成隨機值,作為Python標準庫的一部分。一些相關(guān)模塊包括random模塊、secrets 模塊和uuid模塊。secrets模塊提供加密性強的隨機數(shù),而random模塊提供安全性較差的數(shù)字,可用于游戲、測試數(shù)據(jù)、模擬等。下面將討論這兩種類型的隨機值之間的差異。

隨機值與偽隨機值

“真”隨機數(shù)和偽隨機數(shù)之間的主要區(qū)別:偽隨機數(shù)生成器使用一種算法生成看似隨機但具有確定性的數(shù)字序列。事實上,它們是如此確定,給定相同的種子值(或起始值),它們將可靠地生成相同的數(shù)字序列!另一方面,隨機數(shù)生成器依賴物理過程來創(chuàng)建真正隨機的數(shù)字。

雖然偽隨機數(shù)生成器適用于許多用途,但它們不適用于需要真正隨機性的應(yīng)用,如密碼學(xué)。這是因為知道算法的人可以預(yù)測序列中的下一個數(shù)字。因此,真正的隨機數(shù)生成器對于安全關(guān)鍵應(yīng)用至關(guān)重要。

隨機和加密

正如我們在上一節(jié)中所討論的,如果我們正在編寫游戲或模擬數(shù)據(jù),random模塊是很好的。然而,如果我們處理授權(quán)令牌或其他安全數(shù)據(jù),我們需要secrets模塊。

隨機模塊

這兩個模塊之間還有其他區(qū)別。random模塊是這兩個模塊中較老的一個,自Python版本1以來一直存在。它有一個大型函數(shù)接口,本質(zhì)上是一個類的共享實例random.Random的包裝器。然而,你始終可以構(gòu)造自己的隨機類并使用它。random.Random可以用已知種子實例化隨機類,以給出可復(fù)制的隨機數(shù)序列。如果缺失,將使用基于系統(tǒng)計時器的種子值。

此示例顯示了選擇種子對random.Random類的影響:

"""Creating random integers demo"""
from random import Random, randint

seed = 42
seeded_1 = Random(seed)
seeded_2 = Random(seed)
randomly_seeded = Random()

# Get a random number between 1 and 1000, inclusive
print(seeded_1.randint(1, 1000))
print(seeded_2.randint(1, 1000))
print(randomly_seeded.randint(1, 1000))

# Use the functional interface
print(randint(1,1000))
655
655
161
956

隨機類的兩個實例使用相同的種子實例化,生成了前兩行輸入。每次運行程序時,這些行打印655。(試試看?。?。

最后兩行是使用隨機種子實例和函數(shù)接口(也是隨機種子)創(chuàng)建的。代碼隨每次運行而變化,在這兩行的情況下,數(shù)字排列的任何運行都是完全重合的。

加密模塊

乍一看,在PEP 506中首次描述并首次出現(xiàn)在Python 3.6中的secrets模塊看起來與Python隨機模塊非常不同。許多函數(shù)接口包裝器都已經(jīng)消失,因此,例如,你不能直接導(dǎo)入randint。此外,還有secrets.SystemRandom類將忽略你可能傳遞給它的任何種子值。

然而,如果我們在這些表面差異的下面進行描述,這兩個類非常相似,實際上,從源代碼來看:

  • secrets.SystemRandom類實際上是random.SystemRandom類的別名。

  • random.SystemRandomrandom.Random的子類。因此,一般來說,一個系統(tǒng)中可用的功能在另一個系統(tǒng)也可用。(兩個例外是getstatesetstate,它們沒有在SystemRandom中實現(xiàn))。

內(nèi)部最顯著的區(qū)別是SystemRandom中的核心“隨機化”行為是根據(jù)os.urandom實現(xiàn)的。反過來,urandom函數(shù)被傳遞一個整數(shù),并使用依賴于平臺的加密強隨機值生成器返回許多隨機字節(jié)。

我們現(xiàn)在知道我們可以使用這兩個類中的任何一個,它們基本上是可互換的,但secrets.SystemRandom將更真實地隨機,因此在更安全的環(huán)境中使用。

考慮到這一點,接下來讓我們看一些用例。

生成隨機數(shù)

Randint和Randrange

我們已經(jīng)了解了如何使用randint在特定范圍內(nèi)生成隨機數(shù)。randrange函數(shù)非常相似,只是它不包括上限,而randint的上限是包含的。如果你足夠頻繁地運行這段代碼,第一行輸出會出現(xiàn)5,但第二行不會。

from secrets import SystemRandom
rand = SystemRandom()

# Integers betewen 1 and 5, inclusive
print(rand.randint(1,5))   

# Integers between 1 and 5, but not including 5
print(rand.randrange(1,5))

生成隨機分布

Random和SystemRandom共享了幾種方法,允許你根據(jù)各種分布生成隨機值。這些包括均勻分布(獲得兩個端點之間的浮點值,類似于randint提供的)、高斯(正態(tài))分布等。

例如,我們可以創(chuàng)建一個包含20個虛擬IQ值的列表,這些值沿著與真實人群相同的正態(tài)曲線隨機分布。根據(jù)定義,智商的平均值為100,標準差為15。(順便說一句,為了本示例的目的,我們希望對這種分布建模,即使我們忽略了對這個想法和我們?nèi)绾螠y試它提出的合理批評。)

以下是隨機創(chuàng)建 20 個 IQ 的“群體”的代碼:

"""IQ distribution"""
from secrets import SystemRandom
rand = SystemRandom()
population = [round(rand.gauss(100, 15)) for _ in range(0,20)]
print(population)

當然,輸出會有所不同。這是一個有代表性的運行:

[102, 90, 88, 82, 102, 93, 127, 121, 94, 107, 103, 80, 106, 106, 84, 107, 108, 88, 123, 121]

在Python中進行隨機選擇

在其他語言中,從列表或其他序列中進行選擇通常需要兩個步驟。首先,你得到一個從0到列表上界(長度減1)的隨機數(shù)。然后將該索引應(yīng)用于列表以選擇元素。在Python中,choice和chchoicesices這兩種方法使你能夠同時執(zhí)行這兩個步驟。這使得從任何類型的序列中選擇所需大小的隨機樣本非常容易。

例如,給定上面的代碼,假設(shè)我們想要獲取IQ的總體,并從中選擇一個或多個值。下面是我們可以快速完成的方法:

# Select one IQ at random
print(rand.choice(population))

# Select four IQs at random
print(rand.choices(population, k=4))

輸出(示例):

102
[107,102,88,103]

如何使用 Python 生成隨機字符串

因為在Python中使用隨機方法很容易從序列中選擇隨機選項。通過Random.choice或者Random.choices函數(shù),在Python中創(chuàng)建隨機字符串也很簡單。此外,secrets模塊定義了一些特殊的函數(shù),根據(jù)你的需要,也可以使用這些函數(shù)。

讓我們首先看看一種通用方法,你可以使用它生成多種類型的字符串。字符串模塊包括幾個基本上是硬編碼字符序列的字符串,例如ascii_lowercase(a-z)、ascii_uppercase(A-Z)、ascii_letters、punctuationdigits。Random.choices或者SystemRandom.choices可以調(diào)用其中任何一個來創(chuàng)建所需長度的數(shù)組,然后可以使用str類的join方法將數(shù)組轉(zhuǎn)換為新字符串。

我們在以下示例中結(jié)合了這些步驟:

from string import ascii_letters, digits, punctuation, ascii_lowercase, ascii_uppercase
from secrets import SystemRandom
rand = SystemRandom()

four_digits = "".join(rand.choices(digits, k=4))
ten_mixed_case = "".join(rand.choices(ascii_letters, k=10))
assorted = ascii_letters + punctuation
twenty_assorted = "".join(rand.choices(assorted, k=20))

print(four_digits)
print(ten_mixed_case)
print(twenty_assorted)

代碼輸出:

8782
PLZYOxFLoQ
!mNsKsF;([I#F(c<JcG}

使用Secrets模塊加密隨機字符串

除了如上所示輕松創(chuàng)建隨機字符串外,secrets模塊還提供了幾個函數(shù),可用于生成各種格式的隨機字節(jié)序列。在最低級別,我們可以使用token_bytes函數(shù)生成各種長度的原始“字節(jié)”數(shù)組。

from secrets import token_bytes
b = token_bytes(10)
print(type(b))
print(b)

代碼輸出:

<class 'bytes'>
b'!\x05P\xc6a\x87\xf9~(\xa9'

原始字節(jié)作為加密算法或類似算法的輸入可能很有用,但請記住,它們不會包含有效的UTF-8代碼點,因此不應(yīng)使用此函數(shù)生成字符串。要獲取字符串,可以使用上一節(jié)中的技術(shù)或下面兩個函數(shù)中的一個。

我們可以返回一個字符串,它不是以原始格式獲取字節(jié),而是以十六進制格式再次由隨機字節(jié)組成。這為每個字節(jié)提供了兩個十六進制輸出字符:

from secrets import token_hex
token = token_hex(10)
print(f"Returned a {type(token)} of length: {len(token)}:")
print(token)

代碼輸出:

Returned a <class 'str'> of length: 20:

同一系列中的第三個功能——在某些方面可能是最有用的——是token_urlsafe。此函數(shù)允許我們將隨機字節(jié)字符串轉(zhuǎn)換為稍微修改的base64編碼字符串。在這里,每個字節(jié)平均產(chǎn)生1.3個字符,結(jié)果可以安全地用作URL-例如,表示縮短的URL或用作密碼重置令牌。另一個好處是字符串來自比16位token_hex更大的潛在隨機字符集。

from secrets import token_urlsafe
token = token_urlsafe(15)
print(token)

代碼輸出:

gfN2nGjO7izMPyXs5tvU

使用UUID:在Python中生成隨機且唯一的值

雖然我們在本文中的重點是隨機值,但我們現(xiàn)在想花一些時間討論對于所有實際目的來說都是隨機和唯一的值。解決這個問題的一種非常普遍的方法是通用唯一標識符(UUID)的概念。UUID是一個128位的數(shù)字,不能100%保證是唯一的,但在統(tǒng)計上很可能是唯一的,以至于發(fā)生沖突的機會非常小。

除了大數(shù)字之外,UUID還共享一種通用的表示格式。128位的數(shù)字可以表示為32個十六進制數(shù)字,而UUID添加四個連字符以形成一個36個字符的字符串,以8-4-4-6-12的模式排列。例如:

'967909e3-7231-4040-aae4-8b6b2fb96a0b'

Python模塊uuid有幾個不同的函數(shù),對應(yīng)于許多公認的算法,用于創(chuàng)建此類標識符,但建議使用兩種最常見的類型之一,uuid1和uuid4。

uuid1值是通過將網(wǎng)絡(luò)節(jié)點id(通常意味著網(wǎng)卡的mac地址)與有關(guān)UUID版本和變體的少量信息以及表示高分辨率時間戳的許多位相結(jié)合來創(chuàng)建的。

相反,uuid4值通常包含用于存儲版本和變體信息的6位,以及122位純隨機數(shù)據(jù)。因此,根據(jù)維基百科,盡管原則上可能存在兩個uuid4值的沖突,但在實踐中,“在103萬億個版本4 UUIDs中找到重復(fù)的概率是十億分之一?!薄?/p>

你可以使用Python uuid模塊輕松創(chuàng)建uuid1和uuid4值。正如我們將看到的,字符串表示看起來是相同的,盡管描述uuid1字段中的位更有意義。

from uuid import uuid1, uuid4

print(uuid1())
print(uuid4())

代碼輸出:

bfc89f3e-e6ab-11ec-abfc-4a9b744d17b8
025586c2-50ed-41a6-ae31-bf96b9d79df2

與本文中的大多數(shù)內(nèi)容一樣,當我們說“示例輸出”時,實際上只是他代碼運行其中一次的結(jié)果。當然,至少在uuid4的情況下,如果你運行這段代碼103萬億次,你有十億分之一的機會得到與我相同的結(jié)果。

在結(jié)束對UUID的討論之前,我們在這里提到它們,因為它們是一個被廣泛接受的標準,但正如我們所看到的,uuid4的實現(xiàn)與系統(tǒng)模塊中的許多實用函數(shù)之間有很多重疊。例如,我經(jīng)??吹?code>uuid4函數(shù)用于在數(shù)據(jù)庫中生成主鍵,特別是在NoSQL上下文中,其中可能不支持自動遞增字段。原則上,人們也可以使用secrets.token_hex用于同樣的任務(wù),但uuid4可能會使代碼的意圖更加清晰。

附上產(chǎn)生隨機數(shù)分布的圖以及代碼實現(xiàn):

import random
import matplotlib.pyplot as plt

x = [random.randint(1, 100) for n in range(100)]
y = [random.randint(1, 100) for n in range(100)]
plt.figure(figsize=(8,6), dpi=80)
plt.scatter(x, y)
plt.show()

結(jié)果:

Python隨機值怎么實現(xiàn)

讀到這里,這篇“Python隨機值怎么實現(xiàn)”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領(lǐng)會,如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI