编程学习网 > 编程语言 > Python > Python的random模块:你真的会"随机"吗?
2026
04-16

Python的random模块:你真的会"随机"吗?


很多人写了几年 Python,对 random 的用法还停在 randint(1, 100)。说实话,这个模块里藏的坑,比你想象的大得多。

先说结论

random 产生的不是真随机,是伪随机。如果你拿它做抽奖、生成验证码、或者搞加密相关的东西,大概率已经在生产环境埋雷了。

什么叫伪随机

random 模块底层跑的是Mersenne Twister算法。它拿一个种子值,用确定性的数学公式推算出一串"看起来随机"的数字序列。

关键点来了:只要种子一样,输出永远一样。

这不是bug,是设计。做调试、做测试、做科学实验的时候,可复现的随机性反而是刚需。但你要拿它当加密工具用,那就是在给自己挖坑。

日常最常用的几个函数

random.choice() 从序列里随机抽一个,比写randint再取下标干净多了。一行代码搞定,不用先算索引再去取,可读性直接上一个档次。

random.shuffle() 原地打乱列表。很多人踩过的坑:这玩意儿是原地操作,改变原有列表,不返回新列表。你以为它在返回打乱后的结果,其实返回的是None。这个坑我见过不止一个人踩过。

random.sample() 做不放回抽样,公司年会抽奖就用它。指定抽几个人,它帮你搞定,不用自己写去重逻辑。

random.uniform(a, b) 生成区间内的浮点数,造测试数据很实用。

三个容易翻车的地方

第一个坑是全局状态。random模块内部维护了一个全局Random实例,整个进程共享。多线程环境下,几个线程同时调random.randint(),状态竞争的问题就来了。解决办法是用 random.Random()自己建实例,各用各的,互不干扰。

第二个坑是安全性。Mersenne Twister是可预测的。攻击者收集足够多的输出值,理论上能反推出种子。Python专门提供了secrets模块来处理这类需求。验证码、密码重置链接、会话ID,全部上secrets,别偷懒用random。

第三个坑是不传seed的行为。不传参数的话,random用系统时间做种子。听起来随机吧?但在容器化环境里,如果一堆进程同时启动,时间戳可能完全一样,种子也就撞了。这种场景下,你以为每个进程都有独立的随机序列,实际上可能大家都在输出同一串数字。

场景对应方案

日常开发和测试数据,random随便用。

需要可复现的科学实验,用random.seed固定种子。

密码、token、验证码,切换到secrets模块。

大批量高性能随机数,上 numpy.random。

加密级别的随机数,用os.urandom()。

写在最后

random模块本身没问题,问题是用错了地方。把伪随机当加密随机用,是不少线上事故的直接原因。搞清楚每个工具的边界在哪,非常重要!

以上就是“Python的random模块:你真的会"随机"吗?的详细内容,想要了解更多Python教程欢迎持续关注编程学习网。

扫码二维码 获取免费视频学习资料

Python编程学习

查 看2022高级编程视频教程免费获取