Python random模块详解与加权随机算法实现

Felix
Felix
发布时间:2026-10-13| 6人浏览过
原创

本文详细介绍Python标准库random模块的核心函数,包括生成随机浮点数、整数及序列操作。重点解析加权随机算法的三种Python实现:暴力扩展法、线性遍历法及基于前缀和与二分查找的高效法,对比分析其时间复杂度与适用场景,帮助开发者根据数据规模选择最优方案。

random模块主要用于生成随机数,可用于随机生成数值或从字符串中随机选取元素。

•random.seed(x):用于设定随机数生成器的种子seed。

通常无需手动设置seed,Python会自动处理种子选择。

•random.random():生成一个随机浮点数n,满足0 <= n < 1。

•random.uniform(a,b):生成指定范围内的随机浮点数,生成的随机整数满足a<=n<=b。

•random.randint(a,b):生成指定范围内的随机整数,a为下限,b为上限,满足a<=n<=b;若a=b,则n=a;若a>b,则报错。

•random.randrange([start], stop [,step]):从指定范围[start,stop)内,按指定基数递增的集合中获取一个随机数,基数缺省值为1。

•random.choice(sequence):从序列中获取一个随机元素,参数sequence表示一个有序类型,并不是一种特定类型,泛指list,tuple,字符串等。

•random.shuffle(x[,random]):用于将一个列表中的元素打乱(洗牌),会改变原始列表。

•random.sample(sequence,k):从指定序列中随机获取k个元素作为一个片段返回,不会改变原有序列。

掌握上述基础知识后,接下来实现一个加权随机算法:

加权随机算法通常应用于以下场景:有一个集合S,包含A,B,C,D四项。此时希望随机抽取一项,但各项抽取概率不同,例如希望抽到A的概率是50%,抽到B和C的概率是20%,D的概率是10%。一般来说,可以给各项赋予权重,抽取概率正比于该权重。上述集合转化为:

{A:5,B:2,C:2,D:1}

方法一:

最直观的实现方式如下:

将序列按权重值扩展为:lists=[A,A,A,A,A,B,B,C,C,D],然后调用random.choice(lists)随机选取一个元素。虽然该方法选取的时间复杂度是O(1),但当数据量增大时,空间消耗会显著增加。

# coding:utf-8
import random


def weight_choice(list, weight):
  """
  :param list: 待选取序列
  :param weight: list对应的权重序列
  :return:选取的值
  """
  new_list = []
  for i, val in enumerate(list):
    new_list.extend(val * weight[i])
  return random.choice(new_list)


if __name__ == "__main__":
  print(weight_choice(['A', 'B', 'C', 'D'], [5, 2, 2, 1]))

方法二:

较为常用的实现方式如下:

计算权重总和sum,然后在1到sum之间随机选择一个数R,随后遍历整个集合,统计已遍历项的权重之和,若大于等于R,则停止遍历并选择当前遇到的项。

仍以上述集合为例,sum等于10,若随机数落在1-5之间,则在遍历第一个元素时即退出遍历。这符合预设的选取概率。

选取过程中需要遍历集合,其时间复杂度是O(n)。

# coding:utf-8
import random

list = ['A', 'B', 'C', 'D']


def weight_choice(weight):
  """
  :param weight: list对应的权重序列
  :return:选取的值在原列表里的索引
  """
  t = random.randint(0, sum(weight) - 1)
  for i, val in enumerate(weight):
    t -= val
    if t < 0:
      return i


if __name__ == "__main__":
  print(list[weight_choice([5, 2, 2, 1])])

方法三:

可先对原始序列按权重排序。这样在遍历时,高概率项会更快被遇到,从而减少平均遍历次数(因为rnd递减的速度最快,即先减去最大的数)。

比较{A:5,B:2,C:2,D:1}和{B:2,C:2,A:5,D:1}两种情况。

前者的遍历步数期望是5/10*1+2/10*2+2/10*3+1/10*4=19/10,而后者的期望是2/10*1+2/10*2+5/10*3+1/10*4=25/10。

这种方式提高了平均选取速度,但原序列排序也需要消耗时间。

另一种思路是构建权重值的前缀和序列,生成随机数t后,利用二分法从前缀和序列中查找,此时选取的时间复杂度即为O(logn)。

 

# coding:utf-8
import random
import bisect

list = ['A', 'B', 'C', 'D']


def weight_choice(weight):
  """
  :param weight: list对应的权重序列
  :return:选取的值在原列表里的索引
  """
  weight_sum = []
  sum = 0
  for a in weight:
    sum += a
    weight_sum.append(sum)
  t = random.randint(0, sum - 1)
  return bisect.bisect_right(weight_sum, t)


if __name__ == "__main__":
  print(list[weight_choice([5, 2, 2, 1])])

以上这篇python的random模块及加权随机算法的python实现方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持本站。

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。