random.choices是python 3.6+的带放回加权抽样函数,通过weights(相对权重)或cum_weights(递增累积权重)指定概率,二者不可共存;要求权重非负且和大于0、长度与population一致,k控制抽样数量,默认可重复。

random.choices 的基本用法和权重参数含义
random.choices 是 Python 3.6+ 提供的带放回抽样函数,核心在于通过 weights 或 cum_weights 参数指定每个元素被选中的相对概率。它不改变原序列,也不要求权重归一化——只要求所有权重非负且至少有一个为正。
常见错误是把 weights 当作“概率”直接填小数(如 [0.1, 0.9]),其实填 [1, 9] 效果完全一样;更常见的坑是传入负数或 None 导致 ValueError: weights must be non-negative。
-
weights:每个元素对应一个数值,系统自动做相对比例换算(内部等价于归一化) -
cum_weights:必须是递增的累积权重(如[1, 3, 10]表示三段区间长度为 1、2、7),优先级高于weights - 两个权重参数不能同时传,否则报
TypeError: choices() got multiple values for argument 'weights'
抽样数量、重复与边界情况处理
抽样结果默认可重复(即“有放回”),这是 random.choices 和 random.sample 的关键区别。如果你需要不重复抽样但又带权重,random.choices 不适用——得自己实现轮盘赌或用 numpy.random.choice(..., replace=False)。
-
k参数控制返回列表长度,缺省为1,设为0返回空列表,设为负数会抛ValueError: k must be non-negative - 当输入序列为空且
k > 0,直接报IndexError: Cannot choose from an empty sequence - 权重全为零(如
[0, 0, 0])会触发ValueError: total of weights must be greater than zero
示例:random.choices(['a', 'b', 'c'], weights=[1, 1, 8], k=5) 可能返回 ['c', 'c', 'a', 'c', 'b']。
weights 和 cum_weights 的实际差异与性能影响
多数场景用 weights 更直观;只有当你已有预计算好的累积分布(比如高频调用、权重动态更新),才考虑 cum_weights——它能省去每次求前缀和的开销。
-
weights=[2, 3, 5]等价于cum_weights=[2, 5, 10] -
cum_weights必须严格递增,[2, 5, 5]会报ValueError: cum_weights must be non-decreasing - 底层对
cum_weights做二分查找,大数据量时比weights略快,但差异通常在微秒级,除非单次调用百万次以上,否则不用刻意优化
与 random.sample、numpy.random.choice 的关键区别
别混淆这三个函数:如果需求是「从列表中按权重挑几个不重复的元素」,random.choices 不满足——它天生支持重复;而 random.sample 完全不支持权重;numpy.random.choice 虽支持权重和 replace=False,但要求输入是 array-like,且返回的是 numpy 类型(可能需 .tolist() 转换)。
-
random.choices(population, weights, k)→ 支持权重、允许重复、纯 Python、返回 list -
random.sample(population, k)→ 不支持权重、强制不重复、纯 Python -
np.random.choice(population, size=k, p=probs, replace=True/False)→ 支持权重和是否重复,但p必须是归一化概率数组,且population会被转成 ndarray
真正容易被忽略的是:权重数组长度必须和 population 一致。少一个或多一个元素,都会立刻报 ValueError: weights and population must be the same length——这个检查很硬,没绕过办法。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











