python生成随机数,使用python实现生成随机数
日常工作编程中有各种各样的随机事件,编程中产生随机数也是如此。每当在Python中生成随机数据、字符串或数字时,最好至少大致了解这些数据是如何生成的。所以本文会详细给大家讲解Python是如何生成随机数据的,有需要的可以参考一下。
00-1010 prn random模块数组的加密安全性有多随机numpy.random相关数据生成Random模块和numpy对照表CSPRNG尽可能随机OS . urandom()UUID工程随机性的秘密比较日常工作编程中有各种各样的随机事件,编程中生成随机数也是如此。随机程度如何?说到信息安全,这是最重要的问题之一。每当在Python中生成随机数据、字符串或数字时,最好至少大致了解这些数据是如何生成的。
Python中生成随机数据的不同选项,然后从安全性、通用性、用途、速度等方面比较每个选项。
本文与数学或密码学无关,只进行必要的数学运算,仅此而已。
目录
Python生成的大部分随机数据在科学意义上并不是完全随机的。相反,它是伪随机的:它是使用伪随机数生成器(PRNG)生成的,伪随机数生成器本质上是用于生成看似随机但仍可再现的数据的任何算法。“真”随机数可以由真随机数发生器(TRNG)产生。
也许你在Python中看到过类似random.seed(999)的东西。这个函数调用Python模块random.seed(1234)使用的底层随机数生成器。Random使后续调用生成的随机数具有确定性:输入A总是产生输出b。
也许“随机”和“确定性”这两个词似乎不能共存。为了更清楚地说明这一点,下面是一个极其简化的版本,random(),它通过使用迭代来创建一个“随机”数x=(x * 3)% 19。x最初被定义为一个种子值,然后根据种子转换成确定性的数列。
类NotSoRandom(对象):
定义种子(自身,a=3):
随机数生成器
self.seedval=a
定义随机(自身):
随机数
self . seed val=(self . seed val * 3)% 19
返回self.seedval
_inst=NotSoRandom()
seed=_inst.seed
random=_inst.random
对于范围(10):内的I
种子(123)
打印([random() for _ in range(10)])
[8, 5, 15, 7, 2, 6, 18, 16, 10, 11]
[8, 5, 15, 7, 2, 6, 18, 16, 10, 11]
[8, 5, 15, 7, 2, 6, 18, 16, 10, 11]
[8, 5, 15, 7, 2, 6, 18, 16, 10, 11]
[8, 5, 15, 7, 2, 6, 18, 16, 10, 11]
[8, 5, 15, 7, 2, 6, 18, 16, 10, 11]
[8, 5, 15, 7, 2, 6, 18, 16, 10, 11]
[8, 5, 15, 7, 2, 6, 18, 16, 10, 11]
[8, 5, 15, 7, 2, 6, 18, 16, 10, 11]
[8, 5, 15, 7, 2, 6, 18, 16, 10, 11]
随机性有多随机
如果你对首字母缩略词“RNG”了解不够,再加一个CSPRNG或者加密的安全PRNG。CSPRNG适用于生成敏感数据,如密码、授权码和令牌。给定一个随机字符串,实际上不可能确定哪个字符串出现在随机字符串序列中的字符串之前或之后。
另一个术语,熵,是引入或预期的随机量。例如,中引入的Python模块会定义DEFAULT_ENTROPY=32,这是默认的返回。
回的字节数。
关于 CSPRNG 的一个关键点是它们仍然是伪随机的。它们以某种内部确定性的方式设计,但添加了一些其他变量或具有使它们『足够随机』以禁止返回到任何强制执行确定性的函数的属性。
Python 工具中的 PRNG 和 CSPRNG :
- PRNG 选项包括 Python 标准库中的 random 模块及其基于数组的 NumPy 对应模块 numpy.random。
- Python 的 os、secrets 和 uuid 模块包含用于生成加密安全对象的函数。
PRNG
random 模块
random模块是在 Python 中生成随机数据的最广为人知的工具可,使用Mersenne Twister PRNG 算法作为其核心生成器。
构建一些没有播种的随机数据。该 random.random() 函数返回区间 [0.0, 1.0) 内的随机浮点数。
import randomrandom.random()
0.1250920165739744
random.random()
0.7327868824782764
使用 random.seed(),可以使结果可重现,并且之后的调用链random.seed() 将产生相同的数据轨迹。
随机数序列变为确定性的,或完全由种子值确定。
random.seed(444)random.random()
0.3088946587429545
random.random()
0.01323751590501987
random.seed(444)
random.random()
0.3088946587429545
random.random()
0.01323751590501987
使用 random.randint() 可以使用该函数在 Python 中的两个端点之间生成一个随机整数。数据在整个 [x, y] 区间并且可能包括两个端点。
>>> random.randint(0, 10)2
>>> random.randint(500, 50000)
9991
使用 random.randrange() 可以排除区间的右侧,生成的数字始终位于 [x, y) 范围内,并且始终小于右端点。
random.randrange(1, 10)9
使用 random.uniform(),从连续均匀分布中提取生成位于特定 [x, y] 区间内的随机浮点数。
random.uniform(20, 30)27.42639687016509
random.uniform(30, 40)
36.33865802745107
使用 random.choice() 从非空序列(如列表或元组)中选择随机元素。
items = [A, B, C, D, E]random.choice(items)
B
random.choices(items, k=2)
[A, C]
random.choices(items, k=3)
[C, D, E]
使用 random.sample() 不替换的情况下模拟采样。
random.sample(items, 4)[A, D, B, E]
使用 random.shuffle() 修改序列对象并随机化元素的顺序。
random.shuffle(items)items
[E, B, A, C, D]
生成一系列唯一长度一致的随机字符串的例子,一般用于验证码这种。
from random import Random# 随机生成邮件验证码的随机字符串
def RandomsStr(random_length):
Str =
chars = AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789 # 设置可选字符
length = len(chars) - 1
random = Random()
for i in range(random_length):
Str += chars[random.randint(0, length)]
return Str
RandomsStr(10)
LhK3vFepch
RandomsStr(16)
iGy1g0FO54Cjx3WP
数组 numpy.random
大多数函数都 random 返回一个标量值(单个int、float或其他对象)。生成序列的话可以使用列表生成的方法。
[random.random() for _ in range(5)][0.7401011155476498,
0.9892634439644596,
0.36991622177966765,
0.14950913503744223,
0.4868906039708182]
numpy.random 使用自己的 PRNG,与普通的 random 不太一样。
"""从标准正态分布返回样本
"""
np.random.randn(5)
array([-0.59656657, -0.6271152 , -1.51244475, -1.02445644, -0.36722254])
np.random.randn(3, 4)
array([[ 0.34054183, 1.59173609, -0.5257795 , -0.86912511],
[-0.86855499, -0.64487065, 1.47682128, 1.8238103 ],
[ 0.05477224, 0.35452769, 0.14088743, 0.55049185]])
"""
根据概率随机分配
"""
np.random.choice([0, 1], p=[0.6, 0.4], size=(5, 4))
array([[0, 1, 0, 1],
[0, 1, 1, 1],
[0, 1, 0, 1],
[1, 0, 0, 0],
[0, 0, 0, 0]])
"""
创建一系列随机布尔值
"""
np.random.randint(0, 2, size=25, dtype=np.uint8).view(bool)
array([ True, False, True, True, False, True, False, False, False,
False, False, True, True, False, False, False, True, False,
True, False, True, True, True, False, True])
相关数据的生成
假设要模拟两个相关的时间序列。解决此问题的一种方法是使用 NumPy 的multivariate_normal() 函数,该函数将协方差矩阵考虑在内。换句话说要从单个正态分布的随机变量中提取,需要指定其均值和方差(或标准差)。
def corr2cov(p, s):"""相关性和标准差的协方差矩阵"""
d = np.diag(s)
return d @ p @ d
corr = np.array([[1., -0.40],[-0.40, 1.]])
stdev = np.array([6., 1.])
mean = np.array([2., 0.5])
cov = corr2cov(corr, stdev)
data = np.random.multivariate_normal(mean=mean, cov=cov, size=50)
data[:10]
[[-0.33377432 0.22889428]
[-1.5311996 0.31678635]
[-6.02684472 0.90562824]
[ 5.2696086 0.86518295]
[ 6.43832395 0.36507745]
[-8.49347011 0.68663565]
[-5.05968126 0.55214914]
[ 2.02314646 1.32325775]
[ 0.98705556 -0.63118682]
[ 2.90724439 -1.26188307]]
random模块与NumPy对照表
CSPRNG
尽可能随机 os.urandom()
在不涉及太多细节的情况下,生成依赖于操作系统的随机字节,可以安全地称为密码安全 secretsuuidos.urandom(),在技术上仍然是伪随机的。
唯一的参数是要返回的字节数。
os.urandom(3)b\xa2\xe8\x02
x = os.urandom(6)
x
b\xce\x11\xe7"!\x84
type(x), len(x)
(bytes, 6)
但是这种保存格式不太符合开发的要求。
secrets 最佳保存方式
Python 3.6+ 版本引入的 PEP,secrets模块旨在成为事实上的 Python 模块,用于生成加密安全的随机字节和字符串。
secrets 基本上是一个包装器 os.urandom()。只导出了少数用于生成随机数、字节和字符串的函数。
n = 16# 生成安全令牌
secrets.token_bytes(n)
bA\x8cz\xe1o\xf9!;\x8b\xf2\x80pJ\x8b\xd4\xd3
secrets.token_hex(n)
9cb190491e01230ec4239cae643f286f
secrets.token_urlsafe(n)
MJoi7CknFu3YN41m88SEgQ
# `random.choice()` 的安全版本
secrets.choice(rain)
a
UUID
生成随机令牌的最后一个选项是 Python 的 uuid 模块中的 uuid4() 函数。 UUID 是一个通用唯一标识符,一个 128 位序列(长度为 32 的字符串),旨在『保证跨空间和时间的唯一性』。 uuid4() 是该模块最有用的函数之一,该函数也使用了 os.urandom()。
import uuiduuid.uuid4()
UUID(3e3ef28d-3ff0-4933-9bba-e5ee91ce0e7b)
uuid.uuid4()
UUID(2e115fcb-5761-4fa1-8287-19f4ee2877ac)
可能还看到了其他一些变体:uuid1()、uuid3() 和 uuid5()。它们之间的主要区别在于这 uuid4() 三个函数都采用某种形式的输入,不符合 uuid4() 的『保证跨空间和时间的唯一性』。
除了安全模块(例如 secrets)之外,Python 的 random 模块实际上还有一个很少使用的类,称为 SystemRandom,它使用 os.urandom()。 (反过来,SystemRandom 也被秘密使用。这有点像一个可以追溯到 urandom() 的网络。)
那么为什么不『默认』这个版本? 为什么不『永远安全』,而不是默认使用在密码学上不安全的确定性随机函数?
1.因为有时希望数据具有确定性和可重复性,以供其他人后续使用。
2.时间效率问题。
"""CSPRNG 至少在 Python 中,往往比 PRNG 慢得多。
让我们使用脚本 timed.py 来测试,该脚本使用 timeit.repeat() 比较 randint() 的 PRNG 和 CSPRNG 版本。
"""
import random
import timeit
# CSPRNG 版本依次使用 `SystemRandom()` 和 `os.urandom()`。
_sysrand = random.SystemRandom()
def prng() -> None:
random.randint(0, 95)
def csprng() -> None:
_sysrand.randint(0, 95)
setup = import random; from __main__ import prng, csprng
if __name__ == __main__:
print(Best of 3 trials with 1,000,000 loops per trial:)
for f in (prng(), csprng()):
best = min(timeit.repeat(f, setup=setup))
print(\t{:8s} {:0.2f} seconds total time..format(f, best))
Best of 3 trials with 1,000,000 loops per trial:
prng() 0.93 seconds total time.
csprng() 1.70 seconds total time.
工程随机性的比较
到此这篇关于详解Python中生成随机数据的示例详解的文章就介绍到这了,更多相关Python随机数据内容请搜索盛行IT软件开发工作室以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT软件开发工作室!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。