pin_drop当前位置:知识文库 ❯ 图文

Python random模块入门 - 伪随机数生成器全面使用指南

概述

random 是 Python 标准库中用于生成伪随机数的模块,其核心算法为 Mersenne Twister(梅森旋转算法,MT19937)。该算法具有极长的周期(2^19937 - 1)和良好的统计特性,是科学计算和模拟仿真中最常用的伪随机数生成器之一。

random 模块提供了丰富的随机数生成功能,涵盖:随机浮点数(random)、随机整数(randint、randrange)、随机选择(choice、choices)、随机采样(sample)、随机洗牌(shuffle)、种子控制(seed)以及多种概率分布(均匀分布、正态分布、指数分布等)。

需要注意的是,random 模块生成的是伪随机数,不适合用于安全敏感的场景(如密码生成、加密密钥等),安全场景应使用 secrets 模块。


导入方式

代码示例

# 方式一:导入整个模块(推荐)
import random

# 使用模块前缀调用
random.randint(1, 10)
random.choice(['a', 'b', 'c'])

# 方式二:导入特定函数
from random import randint, choice, shuffle, sample

# 直接使用函数名调用
randint(1, 10)
choice(['a', 'b', 'c'])

# 方式三:创建独立的随机数生成器
rng = random.Random(42)  # 带种子的独立实例
rng.randint(1, 10)

提示:推荐使用 import random 方式导入,避免命名冲突,且代码可读性更好。

函数分类说明

random 模块主要函数分类如下:

类别 函数 说明
基本随机数 random() [0.0, 1.0) 之间的随机浮点数
随机整数 randint(a, b), randrange() 指定范围内的随机整数
随机浮点数 uniform(a, b) [a, b] 之间的随机浮点数
随机选择 choice(seq), choices() 从序列中随机选择元素
随机采样 sample(population, k) 不重复随机采样
随机洗牌 shuffle(x) 原地打乱序列
种子控制 seed(a) 设置种子、获取/恢复状态
正态分布 gauss(mu, sigma) 正态分布随机数
其他分布 expovariate() 等 各种概率分布

各函数返回值因函数而异:random() 返回 float 范围 [0.0, 1.0),randint() 返回 int,choice() 返回序列中的单个元素,shuffle() 返回 None(原地修改)。

代码示例

示例1:基本随机数生成

代码示例

import random

# [0.0, 1.0) 之间的随机浮点数
print(f"random(): {random.random():.6f}")

# 指定范围的随机整数 [a, b]
print(f"randint(1, 100): {random.randint(1, 100)}")

# 指定范围的随机浮点数 [a, b]
print(f"uniform(1, 10): {random.uniform(1, 10):.2f}")

# 带步长的随机整数
print(f"randrange(0, 100, 5): {random.randrange(0, 100, 5)}")  # 0-95中5的倍数

# 获取随机比特
print(f"getrandbits(8): {random.getrandbits(8)}")  # 0-255的随机整数

# 输出:
# random(): 0.725419
# randint(1, 100): 42
# uniform(1, 10): 5.73
# randrange(0, 100, 5): 65
# getrandbits(8): 187

示例2:随机选择与采样

代码示例

import random

# 随机选择一个元素
fruits = ['苹果', '香蕉', '橙子', '葡萄', '西瓜']
print(f"随机水果: {random.choice(fruits)}")

# 随机采样(不重复)
sample = random.sample(fruits, 3)
print(f"采样3个: {sample}")

# 带权重的随机选择(可重复)
colors = ['红', '绿', '蓝']
weights = [5, 3, 2]  # 红色概率最高
picked = random.choices(colors, weights=weights, k=10)
print(f"加权选择10次: {picked}")

# 统计权重选择结果
from collections import Counter
counts = Counter(picked)
for color in colors:
    print(f"  {color}: {counts.get(color, 0)}次")

# 输出:
# 随机水果: 橙子
# 采样3个: ['葡萄', '苹果', '西瓜']
# 加权选择10次: ['红', '红', '绿', '红', '蓝', '红', '绿', '红', '红', '绿']
#   红: 6次
#   绿: 3次
#   蓝: 1次

示例3:随机洗牌与模拟

代码示例

import random

# 洗牌
cards = list(range(1, 11))
print(f"洗牌前: {cards}")
random.shuffle(cards)
print(f"洗牌后: {cards}")

# 模拟掷骰子
print(f"\n掷骰子10次: {[random.randint(1, 6) for _ in range(10)]}")

# 模拟抛硬币
coins = [random.choice(['正面', '反面']) for _ in range(10)]
heads = coins.count('正面')
tails = coins.count('反面')
print(f"抛硬币10次: {coins}")
print(f"正面{heads}次, 反面{tails}次")

# 模拟随机漫步
position = 0
steps = 20
path = [position]
for _ in range(steps):
    step = random.choice([-1, 1])
    position += step
    path.append(position)
print(f"\n随机漫步20步: 起点为0, 终点为{position}")
print(f"路径: {path}")

# 输出:
# 洗牌前: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 洗牌后: [7, 3, 1, 9, 5, 2, 10, 4, 8, 6]
#
# 掷骰子10次: [3, 6, 1, 4, 2, 5, 6, 1, 3, 4]
#
# 抛硬币10次: ['正面', '反面', '正面', '正面', '反面', '正面', '反面', '正面', '正面', '反面']
# 正面6次, 反面4次
#
# 随机漫步20步: 起点为0, 终点为4
# 路径: [0, 1, 0, 1, 2, 1, 2, 3, 2, 1, 2, 3, 4, 3, 4, 5, 4, 3, 2, 3, 4]

实际应用场景

  • 模拟仿真:蒙特卡洛模拟、随机过程模拟、随机漫步

  • 游戏开发:随机事件、随机地图、随机掉落、骰子/卡牌

  • 数据采样:从大数据集中随机抽取样本进行分析

  • 随机测试:生成随机测试数据、模糊测试

  • 随机推荐:从候选列表中随机推荐内容

  • 机器学习:数据集划分、随机初始化、随机搜索


注意事项

注意1:random 模块生成的是伪随机数,不适合用于安全敏感的场景(如密码生成、加密密钥、安全令牌)。安全场景请使用 secrets 模块。

注意2:random 模块的全局函数使用共享的内部状态,在多线程环境中可能产生竞争条件。如需线程安全的随机数生成器,请使用 random.Random() 创建独立实例。

注意3:设置相同的种子(seed)会产生相同的随机数序列,这在测试和复现中很有用,但生产环境通常不应设置固定种子。

注意4:random 模块的默认种子基于系统时间/操作系统随机源,每次运行结果不同。

注意5:randint(a, b) 是闭区间 [a, b],包含 b。这与 range(a, b) 的左闭右开不同,容易混淆。

提示:需要可复现的随机结果时,在程序开头使用 random.seed(42) 固定种子;需要独立随机流时,使用 random.Random(seed) 创建独立实例。

相关方法对比

特性 random secrets numpy.random os.urandom
安全性 不安全(伪随机) 安全(真随机源) 不安全 安全
性能 高 中 极高(向量化) 中
分布支持 丰富 有限 极丰富 无
数组支持 否 否 是 否
线程安全 全局函数不安全 安全 全局函数不安全 安全
典型用途 模拟、采样 密码、令牌 科学计算 加密

小贴士

Mersenne Twister 算法虽然周期极长(2^19937 - 1),但它不是密码学安全的。其内部状态可以通过观察 624 个连续输出值来完全重建,从而预测后续所有随机数。因此在需要安全随机数的场景(如生成密码、API密钥、Session ID)中,务必使用 secrets 模块。

小结

  • random 模块基于 Mersenne Twister 算法生成伪随机数,周期极长,统计特性好

  • 提供随机整数、浮点数、选择、采样、洗牌、分布等丰富功能

  • 不适合安全敏感场景,安全场景使用 secrets 模块

  • 使用 seed() 可以复现随机结果,使用 Random() 创建独立实例

  • randint(a, b) 是闭区间,注意与 range() 的区别


练习题

练习1

使用 random.randint() 模拟掷两个骰子 1000 次,统计点数之和为 7 的次数,并计算概率(理论值约 16.67%)。

练习2

使用 random.choice() 模拟一个简单的猜拳游戏(石头、剪刀、布),人与电脑各出10次,统计胜负。

练习3

使用 random.sample() 从 1 到 100 中随机抽取 5 个不重复的数字,模拟彩票选号。

练习4

使用 random.Random(42) 创建一个独立的随机数生成器,生成 10 个随机整数,然后重新创建相同种子的生成器,验证结果一致。

常见问题

random 模块和 secrets 模块有什么区别?

random 模块基于 Mersenne Twister 算法生成伪随机数,速度快但不安全,适合模拟、游戏、采样等场景。secrets 模块使用操作系统提供的真随机源(如 Windows 的 CryptGenRandom),具有密码学安全性,适合生成密码、令牌、验证码等安全敏感场景。

random.seed() 有什么作用?什么时候应该使用?

random.seed() 用于设置随机数生成器的种子,相同的种子会产生相同的随机数序列。这在需要可复现结果的场景中非常有用:如单元测试、科学实验、机器学习模型训练等。生产环境一般不应设置固定种子,以保证每次运行结果的随机性。

random.choice() 和 random.choices() 有什么区别?

random.choice(seq) 从序列中随机选择一个元素,返回单个值。random.choices(seq, weights, k) 可以带权重进行 k 次随机选择(可重复),返回列表。choices() 还支持 weights 参数指定每个元素的选中概率,适合加权随机选择场景。

random.sample() 和 random.choices() 有什么区别?

random.sample() 是不重复抽样(不放回),适合从总体中抽取不重复的样本,如抽奖、彩票选号。random.choices() 是可重复抽样(有放回),同一个元素可能被多次选中,还支持权重参数。两者的核心区别在于是否允许重复。

random.shuffle() 为什么不返回新列表而是原地修改?

random.shuffle() 原地修改列表是为了节省内存,避免创建新列表的开销。这是 Python 中常见的原地操作模式(如 list.sort()、list.reverse())。如果需要保留原列表,可以在洗牌前先复制:shuffled = original[:],然后 random.shuffle(shuffled)。

标签: Python random模块 随机数 伪随机数 Mersenne Twister 随机采样

本文涉及AI创作

内容由AI创作,请仔细甄别

list快速访问

上一篇: Python math常量详解 - math.pi、math.e、math.inf、math.nan使用指南 下一篇: Python random.random详解 - 均匀分布随机浮点数与蒙特卡洛实战

poll相关推荐