Python Random:生成随机数、选择和样本
Updated on
生成随机数据是编程的基础——从打乱播放列表和抽样调查受访者,到运行蒙特卡洛模拟和创建测试数据集。但Python的random模块有数十个函数,很容易用错。在需要整数时调用random.random(),在需要多个唯一项时使用choice(),或者忘记random不是加密安全的,都可能导致微妙的bug或安全漏洞。
Python的random模块提供了伪随机数生成的综合工具包。本指南涵盖了你常用的每个函数,并附有清晰的示例说明何时使用每个函数。
随机整数
randint(a, b)
返回一个随机整数N,满足a <= N <= b(包含两个端点)。
import random
# Random integer between 1 and 10 (inclusive)
print(random.randint(1, 10)) # e.g., 7
# Simulate a dice roll
dice = random.randint(1, 6)
print(f"You rolled a {dice}")
# Generate random ages for test data
ages = [random.randint(18, 65) for _ in range(5)]
print(ages) # e.g., [34, 52, 21, 45, 28]randrange(start, stop, step)
类似range()但返回一个随机元素。stop值不包含在内。
import random
# Random even number between 0 and 100
print(random.randrange(0, 101, 2)) # e.g., 42
# Random number from 0 to 9
print(random.randrange(10)) # e.g., 7
# Random multiple of 5 from 0 to 100
print(random.randrange(0, 101, 5)) # e.g., 35随机浮点数
random()
返回[0.0, 1.0)范围内的随机浮点数。
import random
print(random.random()) # e.g., 0.7234...
# Scale to any range: random float between 10 and 20
value = 10 + random.random() * 10
print(value) # e.g., 15.23...uniform(a, b)
返回一个随机浮点数N,满足a <= N <= b。
import random
# Random temperature between 98.0 and 99.5
temp = random.uniform(98.0, 99.5)
print(f"Temperature: {temp:.1f}F") # e.g., Temperature: 98.7F
# Random price between 9.99 and 29.99
price = round(random.uniform(9.99, 29.99), 2)
print(f"Price: ${price}")gauss(mu, sigma) -- 正态分布
import random
# Generate normally distributed values (mean=100, std=15)
iq_scores = [round(random.gauss(100, 15)) for _ in range(10)]
print(iq_scores) # e.g., [112, 95, 103, 88, 107, ...]随机选择
choice(seq)
从非空序列中返回一个随机元素。
import random
colors = ['red', 'blue', 'green', 'yellow', 'purple']
print(random.choice(colors)) # e.g., 'green'
# Random character from a string
print(random.choice('abcdefghij')) # e.g., 'f'choices(population, weights, k)
返回有放回抽取(可能有重复)的k个元素列表。支持权重。
import random
# Pick 5 random colors (duplicates allowed)
colors = ['red', 'blue', 'green']
print(random.choices(colors, k=5)) # e.g., ['blue', 'red', 'blue', 'green', 'red']
# Weighted selection (red is 5x more likely)
weighted = random.choices(
['red', 'blue', 'green'],
weights=[5, 1, 1],
k=10
)
print(weighted) # Mostly 'red'sample(population, k)
返回无放回抽取(无重复)的k个唯一元素。
import random
# Lottery numbers: 6 unique numbers from 1-49
lottery = random.sample(range(1, 50), 6)
print(sorted(lottery)) # e.g., [3, 12, 27, 33, 41, 48]
# Random survey sample
employees = ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve', 'Frank']
survey_group = random.sample(employees, 3)
print(survey_group) # e.g., ['Diana', 'Alice', 'Frank']choice vs choices vs sample
| 函数 | 放回 | 返回值 | 用途 |
|---|---|---|---|
choice(seq) | N/A(单个项) | 一个元素 | 随机选择一个项 |
choices(pop, k=n) | 有放回 | n个元素的列表 | 加权随机、模拟 |
sample(pop, k=n) | 无放回 | n个唯一元素的列表 | 抽奖、随机子集 |
洗牌
shuffle(seq)
就地洗牌列表。返回None。
import random
deck = list(range(1, 53)) # 52 cards
random.shuffle(deck)
print(deck[:5]) # e.g., [37, 12, 48, 3, 21]
# Deal 5 cards
hand = deck[:5]
remaining = deck[5:]种子和可重现性
设置种子使随机输出可重现——对测试和调试至关重要。
import random
random.seed(42)
print(random.randint(1, 100)) # Always 81
print(random.random()) # Always 0.0744...
# Reset seed for same sequence
random.seed(42)
print(random.randint(1, 100)) # 81 again
print(random.random()) # 0.0744... again何时使用种子
| 场景 | 使用种子? | 原因 |
|---|---|---|
| 单元测试 | 是 | 可重现的测试结果 |
| 调试 | 是 | 重现确切的bug |
| 模拟(分析) | 是 | 可重现的实验 |
| 游戏(游戏玩法) | 否 | 玩家期望真正的随机性 |
| 安全/加密 | 否(使用secrets) | 种子使输出可预测 |
生成测试数据
import random
import string
def random_string(length=10):
"""Generate a random alphanumeric string."""
chars = string.ascii_letters + string.digits
return ''.join(random.choices(chars, k=length))
def random_email():
"""Generate a random email address."""
name = random_string(8).lower()
domains = ['gmail.com', 'yahoo.com', 'outlook.com']
return f"{name}@{random.choice(domains)}"
def random_user():
"""Generate a random user record."""
first_names = ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve']
last_names = ['Smith', 'Jones', 'Brown', 'Wilson', 'Taylor']
return {
'name': f"{random.choice(first_names)} {random.choice(last_names)}",
'email': random_email(),
'age': random.randint(18, 65),
'score': round(random.uniform(0, 100), 1),
}
# Generate 5 test users
users = [random_user() for _ in range(5)]
for user in users:
print(user)Random与数据科学
对于数据分析工作流,random模块有助于抽样、自助法和创建合成数据集。与pandas结合,你可以快速生成测试DataFrame:
import random
import pandas as pd
random.seed(42)
n = 1000
df = pd.DataFrame({
'age': [random.randint(18, 80) for _ in range(n)],
'income': [round(random.gauss(50000, 15000), 2) for _ in range(n)],
'category': random.choices(['A', 'B', 'C'], weights=[5, 3, 2], k=n),
})
print(df.describe())对于随机数据集的交互式探索,PyGWalker (opens in a new tab)可以将任何pandas DataFrame在Jupyter中转换为Tableau风格的可视化UI:
import pygwalker as pyg
walker = pyg.walk(df)安全警告:random vs secrets
random模块不适合安全用途。如果种子已知,其输出是确定性的和可预测的。对于密码、令牌和加密应用,请使用secrets模块:
import secrets
# Cryptographically secure random token
token = secrets.token_hex(16)
print(token) # e.g., 'a3f2b8c9d1e4f5a6b7c8d9e0f1a2b3c4'
# Secure random integer
secure_int = secrets.randbelow(100)
# Secure random choice
secure_choice = secrets.choice(['option1', 'option2', 'option3'])| 特性 | random | secrets |
|---|---|---|
| 算法 | 梅森旋转(PRNG) | 操作系统熵源(CSPRNG) |
| 确定性 | 是(有种子时) | 否 |
| 速度 | 快 | 较慢 |
| 用途 | 模拟、游戏、测试 | 密码、令牌、加密 |
| 可重现 | 是(使用seed()) | 否 |
FAQ
如何在Python中生成随机整数?
使用random.randint(a, b)获取a和b之间(包含两端)的随机整数。例如,random.randint(1, 10)返回1到10之间的数字。对于不包含上限的范围,使用random.randrange(start, stop)。
random.choice和random.sample有什么区别?
random.choice(seq)返回一个随机元素。random.sample(population, k)返回无放回的k个唯一元素。要选择允许重复的多个项目,使用random.choices(population, k=n)。
如何使随机结果可重现?
在生成随机数之前调用random.seed(value)。使用相同的种子每次都会产生相同的随机值序列。这对单元测试和调试至关重要。
Python的random模块安全吗?
不安全。random模块使用梅森旋转算法,它是确定性的和可预测的。对于密码或令牌等安全敏感的应用,请改用secrets模块,它使用加密安全的随机源。
如何在Python中随机打乱列表?
使用random.shuffle(my_list)就地打乱列表。它修改原始列表并返回None。如果需要保持原始列表不变,先创建副本:shuffled = my_list.copy(); random.shuffle(shuffled)。
总结
Python的random模块涵盖了每种常见的随机化需求:整数用randint,浮点数用uniform,从序列中选择用choice/choices/sample,重新排序用shuffle,可重现性用seed。记住关键区别:choices允许重复(有放回),sample不允许(无放回)。并且永远不要将random用于安全——请改用secrets。