多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Python进阶教程:16_random 模块 —— 使用指南

Python进阶教程:16_random 模块 —— 使用指南 一、什么是 random 模块1.1 一句话定义random是 Python 的内置随机数库用于生成各种类型的随机数、随机选择元素、打乱序列等。1.2 生活比喻现实世界掷骰子、抽奖、洗牌、抛硬币 → 结果不可预测random 模块让程序也能掷骰子、抽奖、洗牌 → 模拟随机行为1.3 ⚠️ 重要概念伪随机数# random 生成的是【伪随机数】不是真正的随机 # 它是通过数学算法梅森旋转算法计算出来的 # 只要种子相同生成的序列就完全相同 # 真正的随机放射性衰变、大气噪声硬件随机数 # 伪随机算法计算看起来随机实际可预测1.4 导入方式# 方式1导入整个模块推荐 import random print(random.randint(1, 10)) # 方式2导入特定函数 from random import randint, choice, shuffle print(randint(1, 10)) # 方式3导入所有不推荐容易命名冲突 from random import *1.5 ⚠️ 安全警告# ❌ random 模块【不适合】用于安全/密码学场景 # 比如生成密码、验证码、加密密钥、抽奖防作弊 # 因为它是伪随机理论上可以被预测 # ✅ 安全场景请用 import secrets secrets.token_hex(16) # 生成安全随机令牌 secrets.randbelow(100) # 安全随机整数二、种子seed—— 控制随机性的开关2.1 什么是种子import random # 种子 随机数生成器的起点 # 相同的种子 → 相同的随机数序列 # 不同的种子 → 不同的随机数序列 # 不设置种子 → 默认用系统时间每次运行都不同 print(random.random()) # 每次运行结果不同 print(random.random()) print(random.random())2.2 设置固定种子import random # 设置种子为 42 random.seed(42) print(random.random()) # 0.6394267984578837 print(random.random()) # 0.025010755222666936 print(random.random()) # 0.27502931836911926 # 重新设置相同的种子 → 完全相同的序列 random.seed(42) print(random.random()) # 0.6394267984578837一模一样 print(random.random()) # 0.025010755222666936 print(random.random()) # 0.275029318369119262.3 种子的实际应用import random # 场景1调试程序时让随机结果可复现 def train_model(seed42): random.seed(seed) # 训练模型时用到随机初始化... weights [random.random() for _ in range(5)] return weights print(train_model(42)) # 每次运行结果相同方便调试 print(train_model(42)) # 和上面一模一样 # 场景2游戏中固定关卡生成 random.seed(12345) # 用关卡编号做种子 level [random.randint(1, 5) for _ in range(10)] print(level) # 玩家每次进入同一关卡地形都一样三、生成随机浮点数3.1 random() —— 最基础的随机数import random # 生成 [0.0, 1.0) 之间的随机浮点数 # 包含 0.0不包含 1.0 print(random.random()) # 例如0.3745401188473625 print(random.random()) # 例如0.9507143064099162 print(random.random()) # 例如0.7319939418114051 # 返回值范围0.0 x 1.0 # 永远不会返回 1.03.2 用 random() 模拟概率事件import random # 模拟 30% 概率触发暴击 if random.random() 0.3: print( 暴击伤害翻倍) else: print(普通攻击) # 模拟抽奖不同概率 def lottery(): r random.random() if r 0.01: # 1% 概率 return 特等奖 elif r 0.05: # 4% 概率 return 一等奖 elif r 0.15: # 10% 概率 return 二等奖 elif r 0.40: # 25% 概率 return 三等奖 else: # 60% 概率 return 谢谢参与 # 测试 10000 次 from collections import Counter results Counter(lottery() for _ in range(10000)) for prize, count in sorted(results.items()): print(f {prize}: {count} 次 ({count/100:.1f}%))3.3 uniform(a, b) —— 指定范围的随机浮点数import random # 生成 [a, b] 之间的随机浮点数两端都包含 print(random.uniform(1, 10)) # 例如6.783214... print(random.uniform(0, 1)) # 例如0.234567... print(random.uniform(-5, 5)) # 例如-2.345678... # 注意uniform 和 random 的区别 # random() → [0.0, 1.0) 不含右端 # uniform(a, b) → [a, b] 包含两端 # 实际应用模拟温度 temperature random.uniform(35.5, 40.0) print(f当前体温{temperature:.1f}℃) # 当前体温37.2℃ # 实际应用模拟坐标 x random.uniform(-100, 100) y random.uniform(-100, 100) print(f随机坐标({x:.2f}, {y:.2f}))四、生成随机整数4.1 randint(a, b) —— 最常用的随机整数import random # 生成 [a, b] 之间的随机整数两端都包含 print(random.randint(1, 6)) # 模拟骰子1~6 print(random.randint(1, 10)) # 1~10 print(random.randint(0, 1)) # 模拟硬币0 或 1 print(random.randint(-10, 10)) # -10 到 10 # ⚠️ 注意randint 两端都包含 # randint(1, 6) 可能返回 1也可能返回 64.2 randint 实际应用import random # 模拟掷骰子 def roll_dice(n1): 掷 n 个六面骰子 return [random.randint(1, 6) for _ in range(n)] print(roll_dice()) # [4] print(roll_dice(2)) # [3, 6] print(roll_dice(3)) # [1, 5, 2] # 模拟猜数字游戏 secret random.randint(1, 100) print(f秘密数字在 1~100 之间) # 随机选择列表索引 fruits [苹果, 香蕉, 橙子, 葡萄, 西瓜] idx random.randint(0, len(fruits) - 1) print(f随机水果{fruits[idx]})4.3 randrange(start, stop, step) —— 带步长的随机整数import random # 从 range(start, stop, step) 中随机选一个 # 注意stop 不包含和 range 一样 # 1~9 之间的随机奇数 print(random.randrange(1, 10, 2)) # 1, 3, 5, 7, 9 中的一个 # 0~100 之间的随机偶数 print(random.randrange(0, 101, 2)) # 0, 2, 4, ..., 100 中的一个 # 0~9 之间的随机整数等价于 randint(0, 9) print(random.randrange(10)) # 对比 randint 和 randrange print(random.randint(1, 6)) # [1, 6] 两端都包含 print(random.randrange(1, 7)) # [1, 7) [1, 6] 不含右端 # 效果一样但 randrange 更灵活支持步长4.4 getrandbits(k) —— 随机比特位import random # 生成一个 k 位的随机整数 # 范围[0, 2^k - 1] print(random.getrandbits(1)) # 0 或 1 print(random.getrandbits(3)) # 0~73位二进制000~111 print(random.getrandbits(8)) # 0~255一个字节 print(random.getrandbits(16)) # 0~65535 # 实际应用快速生成随机布尔值 random_bool bool(random.getrandbits(1)) print(random_bool) # True 或 False # 实际应用生成随机颜色RGB r random.getrandbits(8) g random.getrandbits(8) b random.getrandbits(8) print(f随机颜色rgb({r}, {g}, {b})) # rgb(142, 37, 201)4.5 随机整数方法对比┌─────────────────┬──────────────┬──────────────┬──────────┐ │ 方法 │ 范围 │ 步长 │ 返回类型 │ ├─────────────────┼──────────────┼──────────────┼──────────┤ │ randint(a, b) │ [a, b] │ 固定为1 │ int │ │ randrange(a,b,s)│ [a, b) │ 可自定义 │ int │ │ getrandbits(k) │ [0, 2^k - 1] │ 固定为1 │ int │ └─────────────────┴──────────────┴──────────────┴──────────┘五、序列操作最实用的部分5.1 choice(seq) —— 随机选一个元素import random # 从非空序列中随机选择一个元素 # 从列表中随机选择 fruits [苹果, 香蕉, 橙子, 葡萄] print(random.choice(fruits)) # 例如橙子 # 从字符串中随机选一个字符 print(random.choice(Hello)) # 例如l # 从元组中随机选择 colors (红, 蓝, 绿, 黄) print(random.choice(colors)) # 例如蓝 # 实际应用随机决定今天吃什么 meals [火锅, 烧烤, 麻辣烫, 盖浇饭, 面条, 饺子] print(f今天吃{random.choice(meals)}) # 实际应用石头剪刀布 options [石头, 剪刀, 布] player 石头 computer random.choice(options) print(f你出了{player}电脑出了{computer})5.2 choices(seq, k) —— 有放回地随机选多个import random # 随机选 k 个元素可能重复因为有放回 fruits [苹果, 香蕉, 橙子] # 选 5 个可能有重复 print(random.choices(fruits, k5)) # 例如[苹果, 橙子, 苹果, 香蕉, 苹果] # 带权重选择重要 # weights 参数控制每个元素被选中的概率 print(random.choices( [一等奖, 二等奖, 三等奖, 谢谢参与], weights[1, 5, 20, 74], # 权重比例 k10 )) # 一等奖很少出现谢谢参与最多 # 实际应用模拟有偏硬币正面 60%反面 40% flips random.choices([正面, 反面], weights[60, 40], k1000) from collections import Counter print(Counter(flips)) # Counter({正面: 598, 反面: 402})5.3 sample(population, k) —— 无放回抽样import random # 从序列中随机选 k 个【不重复】的元素 # 原序列不会被修改 numbers [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # 随机抽 3 个不重复的 print(random.sample(numbers, 3)) # 例如[7, 2, 9] # 原列表不变 print(numbers) # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # ⚠️ k 不能大于序列长度 # random.sample([1, 2, 3], 5) # ❌ ValueError # 实际应用抽奖每人最多中一次 participants [Alice, Bob, Charlie, Diana, Eve, Frank] winners random.sample(participants, 3) print(f中奖者{winners}) # [Diana, Alice, Frank] # 实际应用从 range 中高效抽样不需要创建完整列表 # 从 0~9999999 中抽 60 个号码 lottery random.sample(range(10000000), 6) print(f彩票号码{sorted(lottery)}) # 实际应用随机打乱字符串 word HelloWorld shuffled .join(random.sample(word, len(word))) print(shuffled) # 例如lrloWleHdo5.4 shuffle(x) —— 原地打乱列表import random # 将列表【原地】随机打乱顺序 # ⚠️ 没有返回值直接修改原列表 cards [A♠, K♥, Q♦, J♣, 10♠] print(f打乱前{cards}) random.shuffle(cards) print(f打乱后{cards}) # 例如[Q♦, A♠, 10♠, J♣, K♥] # ⚠️ 常见错误 # new_cards random.shuffle(cards) # ❌ new_cards 是 None # 正确做法 cards [A♠, K♥, Q♦, J♣] random.shuffle(cards) new_cards cards # 或者先 copy 再 shuffle # 如果不想修改原列表 original [1, 2, 3, 4, 5] shuffled original.copy() random.shuffle(shuffled) print(original) # [1, 2, 3, 4, 5]不变 print(shuffled) # [3, 1, 5, 2, 4]打乱了 # 实际应用洗牌 deck [f{rank}{suit} for suit in ♠♥♦♣ for rank in A23456789JQK] random.shuffle(deck) print(f洗牌后前5张{deck[:5]}) # 实际应用随机排列题目 questions [Python是什么, 列表和元组的区别, 什么是装饰器] random.shuffle(questions) for i, q in enumerate(questions, 1): print(f第{i}题{q})5.5 序列操作对比┌──────────────────┬────────────┬──────────────┬──────────────┐ │ 方法 │ 选择数量 │ 是否重复 │ 修改原序列 │ ├──────────────────┼────────────┼──────────────┼──────────────┤ │ choice(seq) │ 1个 │ - │ ❌ 不修改 │ │ choices(seq, k) │ k个 │ ✅ 可能重复 │ ❌ 不修改 │ │ sample(seq, k) │ k个 │ ❌ 不重复 │ ❌ 不修改 │ │ shuffle(list) │ 全部 │ - │ ✅ 原地修改 │ └──────────────────┴────────────┴──────────────┴──────────────┘六、高级随机分布6.1 gauss(mu, sigma) —— 正态分布import random # 生成符合正态分布高斯分布的随机浮点数 # mu 均值中心位置 # sigma 标准差分散程度 # 模拟人类身高均值170cm标准差10cm heights [random.gauss(170, 10) for _ in range(1000)] avg sum(heights) / len(heights) print(f平均身高{avg:.1f}cm) # 接近 170 # 大部分值集中在均值附近 # 68% 的值在 [160, 180] 之间±1σ # 95% 的值在 [150, 190] 之间±2σ # 可视化简易版 from collections import Counter buckets Counter(int(h // 5) * 5 for h in heights) for key in sorted(buckets): bar █ * (buckets[key] // 5) print(f{key:3}cm: {bar})6.2 其他分布函数import random # uniform(a, b)均匀分布 # 前面已讲[a, b] 之间等概率 # expovariate(lambd)指数分布 # 模拟等待时间、到达间隔 # 平均到达间隔 5 秒 arrival random.expovariate(1.0 / 5.0) print(f下一个顾客到达时间{arrival:.2f}秒后) # triangular(low, high, mode)三角分布 # 有最可能值众数 # 模拟项目工期最少3天最多10天最可能5天 duration random.triangular(3, 10, 5) print(f预计工期{duration:.1f}天) # betavariate(alpha, beta)Beta分布 # 范围 [0, 1]适合模拟概率/比例 p random.betavariate(2, 5) print(f转化率{p:.4f})6.3 分布速查表┌─────────────────────┬──────────────────────────────────┐ │ 函数 │ 用途 │ ├─────────────────────┼──────────────────────────────────┤ │ random() │ [0,1) 均匀分布 │ │ uniform(a, b) │ [a,b] 均匀分布 │ │ randint(a, b) │ [a,b] 均匀整数 │ │ gauss(mu, sigma) │ 正态分布身高、误差等 │ │ expovariate(lambd) │ 指数分布等待时间、到达间隔 │ │ triangular(l,h,m) │ 三角分布有最可能值 │ │ betavariate(a, b) │ Beta分布概率/比例 │ └─────────────────────┴──────────────────────────────────┘七、状态管理State7.1 getstate() 和 setstate()import random # 保存当前的随机数生成器状态 state random.getstate() # 生成一些随机数 print(random.random()) # 0.6394267984578837 print(random.random()) # 0.025010755222666936 # 恢复到之前保存的状态 random.setstate(state) # 再次生成随机数 → 结果完全相同 print(random.random()) # 0.6394267984578837 print(random.random()) # 0.025010755222666936 # 实际应用游戏中的存档/读档 # 玩家死亡后可以恢复到之前的随机状态重新生成相同的关卡7.2 getstate/setstate vs seedimport random # seed重置到某个已知的起点 random.seed(42) state1 random.getstate() # getstate/setstate保存/恢复到任意时刻的状态 random.random() random.random() state2 random.getstate() # 保存当前位置 random.random() random.random() random.setstate(state2) # 回到 state2 的位置 # 之后的随机数和之前从 state2 开始生成的完全一致八、完整实战案例8.1 密码生成器import random import string def generate_password(length12, use_upperTrue, use_digitsTrue, use_specialTrue): 生成随机密码 chars string.ascii_lowercase # a-z if use_upper: chars string.ascii_uppercase # A-Z if use_digits: chars string.digits # 0-9 if use_special: chars !#$%^* # 确保至少包含每种类型的字符 password [] if use_upper: password.append(random.choice(string.ascii_uppercase)) if use_digits: password.append(random.choice(string.digits)) if use_special: password.append(random.choice(!#$%^*)) # 剩余位数随机填充 remaining length - len(password) password.extend(random.choices(chars, kremaining)) # 打乱顺序 random.shuffle(password) return .join(password) print(generate_password()) # 例如kT3$mN8xPq2! print(generate_password(16)) # 16位密码 print(generate_password(8, use_specialFalse)) # 不含特殊字符8.2 模拟掷骰子游戏import random def roll_dice(): 掷两个骰子 d1 random.randint(1, 6) d2 random.randint(1, 6) return d1, d2, d1 d2 def play_craps(): 简化版掷骰子游戏 d1, d2, total roll_dice() print(f 掷出了 {d1} {d2} {total}) if total in (7, 11): print( 你赢了) elif total in (2, 3, 12): print( 你输了) else: print(f点数是 {total}继续掷...) while True: d1, d2, total roll_dice() print(f 掷出了 {d1} {d2} {total}) if total 7: print( 掷出7你输了) break elif total 4: # 假设目标点是4 print( 掷出目标点你赢了) break play_craps()8.3 随机验证码生成import random import string def generate_captcha(length4): 生成随机验证码字母数字 chars string.ascii_uppercase string.digits code .join(random.choices(chars, klength)) return code print(generate_captcha()) # 例如A7K2 print(generate_captcha(6)) # 例如X9M3P18.4 蒙特卡洛模拟计算 πimport random def estimate_pi(num_samples100000): 用蒙特卡洛方法估算 π inside_circle 0 for _ in range(num_samples): x random.uniform(-1, 1) y random.uniform(-1, 1) # 判断点是否在单位圆内 if x*x y*y 1: inside_circle 1 # 圆的面积 / 正方形面积 π/4 pi_estimate 4 * inside_circle / num_samples return pi_estimate print(f样本数: 100000) print(f估算的 π: {estimate_pi()}) print(f真实的 π: 3.141592653589793) # 样本越多结果越接近真实值九、最佳实践与注意事项9.1 常用方法速查表┌──────────────────────┬────────────────────────────────────┐ │ 方法 │ 用途 │ ├──────────────────────┼────────────────────────────────────┤ │ random() │ [0.0, 1.0) 随机浮点数 │ │ uniform(a, b) │ [a, b] 随机浮点数 │ │ randint(a, b) │ [a, b] 随机整数含两端 │ │ randrange(a, b, s) │ [a, b) 随机整数可设步长 │ │ choice(seq) │ 从序列随机选1个 │ │ choices(seq, k) │ 有放回选k个可带权重 │ │ sample(seq, k) │ 无放回选k个不重复 │ │ shuffle(list) │ 原地打乱列表 │ │ gauss(mu, sigma) │ 正态分布随机数 │ │ seed(n) │ 设置随机种子 │ │ getstate/setstate │ 保存/恢复随机状态 │ └──────────────────────┴────────────────────────────────────┘9.2 常见错误import random # ❌ 错误1shuffle 没有返回值 result random.shuffle([1, 2, 3]) # result 是 None # ✅ 正确 lst [1, 2, 3] random.shuffle(lst) result lst # ❌ 错误2sample 的 k 超过序列长度 random.sample([1, 2, 3], 5) # ValueError! # ✅ 正确先检查长度 if k len(seq): result random.sample(seq, k) # ❌ 错误3用 random 生成密码 password .join(random.choices(string.ascii_letters, k16)) # 不安全 # ✅ 正确用 secrets import secrets password .join(secrets.choice(string.ascii_letters) for _ in range(16)) # ❌ 错误4忘记设置种子导致结果不可复现 # 在机器学习、模拟等场景中记得设置种子 random.seed(42)9.3 选择指南需要1个随机元素 → choice() 需要多个允许重复 → choices() 需要多个不允许重复 → sample() 需要打乱顺序 → shuffle() 需要随机整数 → randint() 或 randrange() 需要随机浮点数 → random() 或 uniform() 需要正态分布 → gauss() 需要安全随机密码等 → secrets 模块十、一句话总结random 模块 Python 的骰子工厂核心记忆randint(a, b)→ 随机整数choice(seq)→ 随机选一个sample(seq, k)→ 随机选k个不重复shuffle(list)→ 打乱列表安全场景用secrets不用random
返回列表