上周帮同事看一个抽奖脚本,random.randint(1, 10) 每次运行都出同一个数,他还以为电脑坏了。翻到循环里一行 random.seed(42),问题就清楚了:种子固定,序列就固定。
python随机数靠的是 random 模块,默认用当前时间做种子,正常调用不需要自己 seed。只有在复现实验、调试对拍时才固定种子,平时写上反而添乱。
randint 和 randrange 差在哪
random.randint(1, 6) 两头都包含,能出 1 和 6,模拟骰子正好。random.randrange(1, 6) 只到 5,跟 range 的规则一样。想要 0 到 1 之间的小数用 random.random(),要指定区间的小数用 random.uniform(1.5, 3.5)。
从列表里抽一个用 random.choice(names),抽多个不重复用 random.sample(names, 3),注意 sample 的第二个参数不能超过列表长度,超了直接抛 ValueError。想原地打乱顺序用 random.shuffle(cards),它没有返回值,写 cards = random.shuffle(cards) 会得到 None。
抽奖和验证码别用同一个函数
random 模块是伪随机,给定种子序列可预测,做活动抽奖、发红包够用,但验证码、重置密码令牌这类不能拿它生成。标准库有 secrets 模块,secrets.randbelow(1000000) 或者 secrets.token_hex(16),底层取系统随机源,安全得多。
结果老是重复怎么查
先搜代码里的 seed,再看是不是每次运行都重新启动了解释器、把随机结果写死缓存了。还有一种情况:在列表推导里调用函数,结果顺序看起来固定,其实是数据本身有序,不是随机数的问题。
我的用法很简单:业务里的普通随机用 random,碰安全就用 secrets;种子只在测试里出现。记住这两条,python随机数基本不会出岔子。