一、什么是 random 模块?
1.1 一句话定义
random 是 Python 的内置随机数库,用于生成各种类型的随机数、随机选择元素、打乱序列等。
1.2 生活比喻
- 现实世界
- random 模块:让程序也能"掷骰子"、"抽奖"、"洗牌" → 模拟随机行为
1.3 ⚠️ 重要概念:伪随机数
# random 生成的是【伪随机数】,不是真正的随机!# 它是通过数学算法(梅森旋转算法)计算出来的# 只要"种子"相同,生成的序列就完全相同# 真正的随机:放射性衰变、大气噪声(硬件随机数)# 伪随机:算法计算,看起来随机,实际可预测
1.4 导入方式
# 方式1:导入整个模块(推荐)import randomprint(random.randint(1, 10))# 方式2:导入特定函数from random import randint, choice, shuffleprint(randint(1, 10))# 方式3:导入所有(不推荐,容易命名冲突)from random import *
1.5 ⚠️ 安全警告
# ❌ random 模块【不适合】用于安全/密码学场景!# 比如:生成密码、验证码、加密密钥、抽奖防作弊# 因为它是伪随机,理论上可以被预测# ✅ 安全场景请用:import secretssecrets.token_hex(16) # 生成安全随机令牌secrets.randbelow(100) # 安全随机整数
二、种子(seed)—— 控制随机性的"开关"
2.1 什么是种子?
import random# 种子 = 随机数生成器的"起点"# 相同的种子 → 相同的随机数序列# 不同的种子 → 不同的随机数序列# 不设置种子 → 默认用系统时间(每次运行都不同)print(random.random()) # 每次运行结果不同print(random.random())print(random.random())
2.2 设置固定种子
import random# 设置种子为 42random.seed(42)print(random.random()) # 0.6394267984578837print(random.random()) # 0.025010755222666936print(random.random()) # 0.27502931836911926# 重新设置相同的种子 → 完全相同的序列!random.seed(42)print(random.random()) # 0.6394267984578837(一模一样!)print(random.random()) # 0.025010755222666936print(random.random()) # 0.27502931836911926
2.3 种子的实际应用
import random# 场景1:调试程序时,让随机结果可复现def train_model(seed=42): random.seed(seed) # 训练模型时用到随机初始化... weights = [random.random() for _ in range(5)] return weightsprint(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.0print(random.random()) # 例如:0.3745401188473625print(random.random()) # 例如:0.9507143064099162print(random.random()) # 例如:0.7319939418114051# 返回值范围:0.0 <= x < 1.0# 永远不会返回 1.0!
3.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 Counterresults = 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~6print(random.randint(1, 10)) # 1~10print(random.randint(0, 1)) # 模拟硬币:0 或 1print(random.randint(-10, 10)) # -10 到 10# ⚠️ 注意:randint 两端都包含!# randint(1, 6) 可能返回 1,也可能返回 6
4.2 randint 实际应用
import random# 模拟掷骰子def roll_dice(n=1): """掷 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 和 randrangeprint(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 或 1print(random.getrandbits(3)) # 0~7(3位二进制: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, k=5))# 例如:['苹果', '橙子', '苹果', '香蕉', '苹果']# 带权重选择(重要!)# weights 参数控制每个元素被选中的概率print(random.choices( ["一等奖", "二等奖", "三等奖", "谢谢参与"], weights=[1, 5, 20, 74], # 权重比例 k=10))# 一等奖很少出现,谢谢参与最多# 实际应用:模拟有偏硬币(正面 60%,反面 40%)flips = random.choices(["正面", "反面"], weights=[60, 40], k=1000)from collections import Counterprint(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) # 例如:"lrloWleHdo"
5.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 Counterbuckets = 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分布(概率/比例) │└─────────────────────┴──────────────────────────────────┘
七、状态管理(State)
7.1 getstate() 和 setstate()
import random# 保存当前的随机数生成器状态state = random.getstate()# 生成一些随机数print(random.random()) # 0.6394267984578837print(random.random()) # 0.025010755222666936# 恢复到之前保存的状态random.setstate(state)# 再次生成随机数 → 结果完全相同!print(random.random()) # 0.6394267984578837print(random.random()) # 0.025010755222666936# 实际应用:游戏中的"存档/读档"# 玩家死亡后,可以恢复到之前的随机状态,重新生成相同的关卡
7.2 getstate/setstate vs seed
import 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 randomimport stringdef generate_password(length=12, use_upper=True, use_digits=True, use_special=True): """生成随机密码""" 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 += "!@#%^&*")) # 剩余位数随机填充 remaining = length - len(password) password.extend(random.choices(chars, k=remaining)) # 打乱顺序 random.shuffle(password) return ''.join(password)print(generate_password()) # 例如:kT3$mN8xPq2!print(generate_password(16)) # 16位密码print(generate_password(8, use_special=False)) # 不含特殊字符
8.2 模拟掷骰子游戏
import randomdef roll_dice(): """掷两个骰子""" d1 = random.randint(1, 6) d2 = random.randint(1, 6) return d1, d2, d1 + d2def 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("🎉 掷出目标点,你赢了!") breakplay_craps()
8.3 随机验证码生成
import randomimport stringdef generate_captcha(length=4): """生成随机验证码(字母+数字)""" chars = string.ascii_uppercase + string.digits code = ''.join(random.choices(chars, k=length)) return codeprint(generate_captcha()) # 例如:A7K2print(generate_captcha(6)) # 例如:X9M3P1
8.4 蒙特卡洛模拟(计算 π)
import randomdef estimate_pi(num_samples=100000): """用蒙特卡洛方法估算 π""" 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_estimateprint(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# ❌ 错误1:shuffle 没有返回值result = random.shuffle([1, 2, 3]) # result 是 None!# ✅ 正确:lst = [1, 2, 3]random.shuffle(lst)result = lst# ❌ 错误2:sample 的 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, k=16)) # 不安全!# ✅ 正确:用 secretsimport secretspassword = ''.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)shuffle(list)- 安全场景用
secrets,不用 random!