您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“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.SystemRandom
是random.Random
的子類。因此,一般來說,一個系統(tǒng)中可用的功能在另一個系統(tǒng)也可用。(兩個例外是getstate
和setstate
,它們沒有在SystemRandom
中實現(xiàn))。
內(nèi)部最顯著的區(qū)別是SystemRandom中的核心“隨機化”行為是根據(jù)os.urandom
實現(xiàn)的。反過來,urandom
函數(shù)被傳遞一個整數(shù),并使用依賴于平臺的加密強隨機值生成器返回許多隨機字節(jié)。
我們現(xiàn)在知道我們可以使用這兩個類中的任何一個,它們基本上是可互換的,但secrets.SystemRandom
將更真實地隨機,因此在更安全的環(huán)境中使用。
考慮到這一點,接下來讓我們看一些用例。
我們已經(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]
在其他語言中,從列表或其他序列中進行選擇通常需要兩個步驟。首先,你得到一個從0到列表上界(長度減1)的隨機數(shù)。然后將該索引應(yīng)用于列表以選擇元素。在Python中,choice
和chchoices
ices這兩種方法使你能夠同時執(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中使用隨機方法很容易從序列中選擇隨機選項。通過Random.choice
或者Random.choices
函數(shù),在Python中創(chuàng)建隨機字符串也很簡單。此外,secrets模塊定義了一些特殊的函數(shù),根據(jù)你的需要,也可以使用這些函數(shù)。
讓我們首先看看一種通用方法,你可以使用它生成多種類型的字符串。字符串模塊包括幾個基本上是硬編碼字符序列的字符串,例如ascii_lowercase
(a-z)、ascii_uppercase
(A-Z)、ascii_letters
、punctuation
和digits
。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}
除了如上所示輕松創(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
雖然我們在本文中的重點是隨機值,但我們現(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)”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領(lǐng)會,如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(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)容。