Python如何生成随机数?常用方法详解

来源:IT编程作者:小黄人头衔:程序员
导读:本期聚焦于小黄人创作的《Python如何生成随机数?常用方法详解》,敬请观看详情。为什么 Python 每次生成的随机数看起来不一样,背后其实依赖伪随机数生成器?如果程序只使用 random 模块生成密码或令牌,可能留下安全隐患。本文从 random 模块的常用函数讲起,对比 random、randint、uniform、choice、sample 的适用场景,再说明 random.seed 如何让结果可复现,以及默认种子为什么来自系统熵源。随后重点介绍 secrets 模块,它基于 os.urandom 提供密码学强度的随机数,适合生成令牌、验证码和会话 ID。对于数组运算场景,文章还会简要梳理 NumPy 中 default_rng 与 Generator 的用法,并给出性能与分布方面的选择思路。通过完整代码示例和避坑建议,帮助读者在不同场景下选出正确方案。

Python 生成随机数主要依赖标准库中的 random 模块和 secrets 模块,科学计算场景还会使用 NumPy 提供的随机数工具。三者定位不同:random 模块适合模拟、游戏、抽样等普通需求;secrets 模块面向密码、令牌等安全敏感场景;NumPy 则擅长批量生成数组形式的随机数。理解它们之间的差异,是避免把不安全的随机数用于安全场景的关键。

Python如何生成随机数?常用方法详解

一、random模块:基础随机数生成

random 模块基于梅森旋转算法实现,是一个伪随机数生成器。它生成的数字序列由初始种子决定,但普通使用时种子来自系统时间或操作系统提供的熵,因此每次运行通常会得到不同结果。处理一般随机需求时,random 模块的接口足够直观。

最常用的函数包括 random()randint()uniform()randrange()choice()shuffle()sample()random() 返回 0 到 1 之间的浮点数,randint(a, b) 返回包含两端点的整数,uniform(a, b) 返回指定区间的浮点数。选择元素时,choice() 从序列中随机取一个元素,sample() 可以无放回地抽取多个元素,shuffle() 则原地打乱列表。下面这段代码展示了这些基础用法。

import random

# 0 到 1 之间的浮点数
print(random.random())

# 1 到 10 之间的整数,包含两端
print(random.randint(1, 10))

# 1.5 到 3.5 之间的浮点数
print(random.uniform(1.5, 3.5))

# 从 0 到 100、步长为 5 的序列中随机选择
print(random.randrange(0, 101, 5))

items = ['apple', 'banana', 'cherry', 'date']
print(random.choice(items))    # 随机选择一个元素
random.shuffle(items)          # 原地打乱列表
print(items)
print(random.sample(items, 2)) # 随机抽取 2 个不重复元素

需要特别注意的是,randint(a, b) 包含右端点,这与 Python 切片习惯不同;如果在循环中重复调用 random.choice,要清楚它是有放回抽样,可能出现重复元素。若需要无重复抽样,直接使用 random.sample 更合适。

二、随机种子与结果可重复

伪随机数生成器的核心特点是:只要种子相同,生成的随机数序列就完全一致。random.seed() 可以显式设置种子,这在调试、测试和复现实验时非常有用。相同种子会保证同一进程内、相同调用顺序下得到相同结果。

下面示例两次使用 seed(42),可以看到输出序列相同。如果去掉 seed,每次运行结果通常不同。

import random

random.seed(42)
print(random.randint(1, 100))
print(random.random())

random.seed(42)
print(random.randint(1, 100))
print(random.random())

如果没有显式调用 seed,Python 会在导入 random 模块时从系统熵源获取种子。这个熵源在大多数操作系统中来自 os.urandom,质量较好。需要注意的是,不要为了提高可复现性而把 random.seed 当作安全机制,固定种子意味着攻击者可以预测后续随机数。对于多线程程序,random 模块的全局函数共享内部状态,多个线程同时调用可能导致结果不可控,必要时可为每个线程创建独立的 random.Random() 实例。

三、secrets模块:密码学安全的随机数

secrets 模块是 Python 标准库中用于生成密码学安全随机数的模块,底层基于 os.urandom,而 os.urandom 又使用操作系统提供的加密安全随机源。它生成的随机数不可预测,适合生成密码重置令牌、会话 ID、验证码和加密盐值。

secrets 的常用函数与 random 类似,但更精简:secrets.randbelow(n) 返回 0 到 n 之间的整数,secrets.choice(seq) 从序列中安全选择元素,secrets.token_hex(nbytes) 生成十六进制令牌,secrets.token_urlsafe(nbytes) 生成适合放在 URL 中的安全字符串。下面是实际示例。

import secrets

# 生成 16 字节的十六进制令牌
token = secrets.token_hex(16)
print(token)

# 生成适合 URL 的安全字符串
url_safe = secrets.token_urlsafe(24)
print(url_safe)

# 从列表中安全选择元素
print(secrets.choice(['red', 'green', 'blue']))

# 生成 0 到 99 之间的安全随机整数
print(secrets.randbelow(100))

不要把 random 模块用于安全令牌。即使设置了随机种子,random 的输出仍可预测。安全的替代方案是 secrets.token_urlsafe 或使用标准库 uuid 模块的 uuid4,但 uuid4 底层也依赖 os.urandom。对于验证码、短令牌等场景,secrets.randbelowsecrets.choice 就足够,关键是不要为了简短而牺牲随机空间,建议令牌长度不低于 16 字节。

四、NumPy中的随机数生成

如果需要在数组或矩阵中批量生成随机数,NumPy 提供的随机数工具比 Python 标准库更高效。新版本推荐使用 np.random.default_rng() 创建 Generator 对象,而不是直接调用旧版全局函数 np.random.rand 等。Generator 使用更现代的 PCG64 算法,性能更好,接口也更清晰。

import numpy as np

rng = np.random.default_rng(12345)

# 生成形状为 (3,) 的随机浮点数组
print(rng.random(3))

# 生成 0 到 9 之间的 5 个随机整数
print(rng.integers(0, 10, size=5))

# 从给定列表中随机选择,生成形状为 (4,) 的数组
print(rng.choice(['a', 'b', 'c'], size=4))

Generator 支持 randomintegerschoicenormalpermutation 等方法,可以一次生成指定形状的数组。与标准库 random 一样,default_rng 接受整数种子时结果可复现。需要注意,NumPy 随机数生成器与 Python random 模块互不影响,两者维护各自的内部状态。如果项目同时使用标准库和 NumPy,不要假设它们共享随机源。

五、常见误区与选择建议

第一个常见误区是认为 random.randint 足够安全。实际上它只是伪随机,攻击者可以在获得足够多输出后预测后续值。任何涉及密码、令牌、加密密钥的场景都必须改用 secrets 或操作系统级随机源。

第二个误区是滥用 random.sample 处理大数据。random.sample 对序列长度和抽样数量较敏感,如果从超大列表中抽取大量样本,内存和时间开销可能较高。此时可考虑使用 random.randrange 配合去重,或在 NumPy 中使用 generator.choice(..., replace=False)

选择建议如下:

  • 普通模拟、游戏、随机排序:使用 random 模块。
  • 需要结果可复现:设置 random.seednp.random.default_rng(seed)
  • 密码、令牌、验证码:使用 secrets 模块。
  • 批量数值计算:使用 numpy.random.Generator

理解不同随机数工具的安全边界和性能特点,能帮助开发者在正确场景下做出选择,避免安全隐患,也能提升程序执行效率。

Python随机数random模块secrets模块修改时间:2026-08-30 01:41:51

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。