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() 返回 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)创建独立实例。
相关方法对比
小贴士
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)。
本文涉及AI创作
内容由AI创作,请仔细甄别