news 2026/10/9 18:47:44

计算机二级Python random库全攻略:函数用法与上机实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
计算机二级Python random库全攻略:函数用法与上机实战

计算机二级Python中的random库:从题型解析到上机实操全攻略

每年计算机二级考试一到考前冲刺阶段,问得最多的问题就是"random库到底要掌握哪些函数""洗牌和抽样用的都是哪个方法"——说实话,这个库在Python标准库里属于"看着容易、考起来很刁钻"的类型。它不像print、for循环那样一看就懂,但因为它出题组合性强,选择题一道、编程题经常作为功能模块被嵌套在应用题里,所以备考阶段花半天时间把它彻底吃透,性价比其实非常高。

这篇文章我把random库在二级考试里可能出现的所有考察角度过一遍:先看清楚考纲到底圈定了什么范围,再把核心函数的用法逐个拆开,结合考试常见题型给出可以直接背诵的代码模板,最后分享几个我在上机练习时踩过的坑。不管是刚开始复习还是临近考试想突击,按这个顺序过一遍都能把random相关的分拿稳。

1. 先摸清二级考试对random库的"圈题范围"

很多同学备考标准库时有个误区:看到官方文档一大堆函数就慌,觉得每个都要背。实际上计算机二级Python科目(考试代码Python,大纲对应《全国计算机等级考试二级Python语言程序设计考试大纲》)对random库的考察范围非常明确,不会超纲到让你手写Mersenne Twister算法,也不会考random模块底层实现的数学原理。你得先知道它的边界,复习才不会扔进大海捞针。

1.1 考纲规定的必备函数清单

我对照大纲和历年真题,把random库在二级考试中的高频函数整理如下:

函数功能出题频率备注
random.random()生成[0.0, 1.0)的随机浮点数极高选择、程序填空都常客
random.uniform(a, b)生成[a, b]或[a, b)区间的随机浮点数中注意两端点的开闭规则
random.randint(a, b)生成[a, b]的随机整数极高两端都是闭区间
random.randrange(start, stop[, step])按步长在某范围内选整数高与range规则完全一致
random.choice(seq)从序列中随机选一个元素高序列可为列表、字符串、元组
random.choices(seq, weights=None, k=1)可带权重地选k个元素(可重复)中低新大纲边缘考点
random.sample(seq, k)从序列中不重复地抽k个元素中返回新列表,不修改原序列
random.shuffle(seq)原地打乱序列顺序高会修改原列表
random.seed(a=None)初始化随机数种子极高上机题复现结果的关键

这9个函数就是复习主线。其余的random.getstate()、random.setstate()、random.getrandbits()在二级大纲里基本不考,备考时可以先放一边。有精力的同学了解名字就行,不要在边上耗时间。

1.2 二级真题里的random库到底怎么出

从真题分布来看,random库在考试里的出场方式大概有三种:

  • 选择题直接考函数含义与参数:比如给一段代码问输出结果是什么,或者给一个需求让选"能实现这个功能"的函数。这种题考察的是你对函数边界条件的理解,比如randint(1, 5)到底包不包括5,random()的范围到底是[0,1)还是[0,1]。
  • 程序填空题考函数调用与参数搭配:给你半个程序,让你填出缺失的random函数调用。这类题通常埋在模拟类、抽奖类、抽样统计类的小程序里。
  • 程序设计题把random作为功能模块:比如让你生成随机验证码、随机点名器、掷骰子模拟、抽样求平均值等。这种情况下一般不会单独考random,而是要求你综合运用列表、循环、条件判断,random只管"产生随机性"这一步。

所以结论很直接:备考策略不是把random库文档背下来,而是把上面9个函数的"输入参数、输出范围、是否原地修改、是否可重复"这四个维度的边界记牢,然后通过刷题把函数组合使用的感觉练出来。

2. 核心函数逐个拆解:参数边界比函数名更重要

random库的函数用法,说穿了没有什么高深的东西,但考试最喜欢在"边界条件"上做文章。我对每个核心函数做一个带陷阱标注的拆解,这些细节都是历年考生栽过跟头的地方。

2.1 random.random()与random.uniform():浮点数里的开闭区间

先看最简单的。

import random # random.random():生成[0.0, 1.0)之间的随机浮点数 x = random.random() print(x) # 可能输出 0.0,但永远不可能输出 1.0

random.random()不接收任何参数,每次调用返回一个float类型的数据,范围是左闭右开——0.0可能被取到,1.0永远取不到。这个"右开"设计不是因为偷懒,而是和计算机表示概率区间的习惯一致:当你需要生成某范围内的小数时,[0, 1)这个区间做线性变换更不容易越界。

random.uniform(a, b)则是在两个指定数之间生成随机浮点数:

y = random.uniform(2, 3) # 生成[2, 3]之间的浮点数,也可能等于3.0

这里有个很容易混淆的点:官方文档写的是"返回a与b之间的随机浮点数,包含两端点(取决于浮点舍入)"。也就是说,理论上uniform(2, 3)有可能返回2.0,也有可能返回3.0,但实际上由于浮点精度问题,取到端点的概率极小。考试判断题如果写"uniform产生的数不包含端点",那是错的;如果写"包含端点",在官方语义上算对。复习时知道它和random()的区别:random()是固定的[0,1)半开区间,uniform(a,b)与端点关系更宽松。

我个人建议大家记忆时用这样一个口诀:random()看成一个标准的电子骰子——最小为0,永远掷不出1;uniform(a,b)就是把这个骰子搬到a和b之间,端点理论上可能碰到。这样在选择题里判断范围时就不容易出错。

2.2 randint与randrange:整数取值的两副面孔

整数随机是考试出题率最高的点,randint和randrange经常混着考。

# randint(a, b):闭区间[a, b],两端都包含 a = random.randint(1, 6) # 模拟掷骰子:1, 2, 3, 4, 5, 6 都算合法输出 print(a) # randrange(start, stop, step):与range规则一致,包含start,不包含stop b = random.randrange(0, 10, 2) # 可能输出0, 2, 4, 6, 8,不可能输出10 c = random.randrange(10) # 等价于randrange(0, 10):输出0~9

关键差异在于:randint(1, 6)的右边界6是闭的,能输出6;而randrange(0, 10)的右边界10是开的,永远输出不了10。类比一下:randint像是"抽中头和尾都算数"的福利彩票,randrange更像是range()那个序列生成器——写range(0, 10)的时候你也知道生成的数不到10。

另外randrange支持步长参数,这在模拟等差数列随机抽取时很实用。二级考试里出现过这样一道选择题:

random.randrange(1, 10, 3)

问可能的输出是哪个。分析一下:1到9(因为右开)之间步长为3,所以可能值是1, 4, 7——10不可能,2不可能,0也不可能。这种题考的就是"你知不知道它和range的规则完全一致"。

2.3 choice、choices与sample:抽一个、抽多个(可重复)、抽多个(不重复)

这三个是"抽样家族",但它们之间最容易搞混。

# choice:从一个非空序列中随机选一个元素 seq = ["一等奖", "二等奖", "三等奖", "谢谢参与"] prize = random.choice(seq) print(prize) # 四者之一 # choices:可带权重地抽k个,允许重复 results = random.choices(["红", "绿", "蓝"], weights=[5, 3, 2], k=10) print(results) # 可能输出 ['红', '蓝', '红', '红', '绿', ...] # 注意:列表长度为k,很可能出现重复元素 # sample:不重复地抽k个,返回新列表 sampled = random.sample(range(100), 10) print(sampled) # 从0~99中抽取10个不重复的编号

三者区别用生活化类比解释:

  • choice是"从碗里拿一颗糖";
  • choices是"从碗里拿糖,拿一颗记一下口味,放回去,再拿一颗,又放回去……于是可能连续两次拿到同一个口味";
  • sample是"一把抓走k颗糖,碗里带走的不可能重复,而且原碗里的糖总数会变少"。

考试中最常见的出题点是:sample抽取后原序列不变,只是返回一个新的列表;choices的权重参数是weights,传入的权重大小对应每个元素被选中的概率权重。注意choices的k不写默认为1,此时返回的是一个列表,而不是单个元素——random.choices(seq)的结果是[x]这种单元素列表,和random.choice(seq)返回x不同。这个细节在判断题、程序输出结果题里容易被设坑。

2.4 shuffle:会"原地改原列表"的破坏性操作

random.shuffle(seq)的作用是把列表顺序随机打乱。它的关键点在于:直接修改原列表,且返回值为None。

cards = [1, 2, 3, 4, 5] result = random.shuffle(cards) print(cards) # 顺序可能变成 [3, 1, 5, 2, 4] 之类 print(result) # 输出 None

很多初学者在这里踩坑:写了new_list = random.shuffle(old_list),然后发现new_list是None——这是因为shuffle是原地操作,不是返回新列表。如果你需要保留原列表,得先复制再打乱:

import copy original = [1, 2, 3, 4, 5] temp = copy.copy(original) # 或 original[:] random.shuffle(temp) print(original) # 不受影响 print(temp) # 打乱后的副本

另外,shuffle只对可变序列有效,比如列表;字符串和元组是不可变类型,无法原地shuffle。如果想打乱字符串,正确做法是先转成列表、打乱、再重新拼接。真题里有道程序填空题就是把字符串转列表、shuffle、再join,这个套路背下来。

s = "abcd" lst = list(s) random.shuffle(lst) s_shuffled = "".join(lst) print(s_shuffled) # 四字母随机重排

2.5 seed:让"随机"变成"可复现",上机考试的关键点

random.seed(a)是设置随机数种子的函数。同一台机器上,只要种子相同,随后生成的随机数序列就完全一致。这个特性在二级考试里的作用极其重要——因为上机评卷需要可重复性。

random.seed(10) print(random.randint(1, 100)) # 第一次运行输出某个值 print(random.randint(1, 100)) # 第二次运行输出另一个值 random.seed(10) # 重新设定同样的种子 print(random.randint(1, 100)) # 又回到了第一次运行时的第一个值 print(random.randint(1, 100)) # 第二次运行时的第二个值

这个机制背后的原理是:random库用的是伪随机数生成器,伪随机并不是"真正不可预测",而是由一个初始种子通过确定性的数学运算不断迭代产生数列。种子就是这条数列的"起点",起点一样,后面的数列必然一样。

二级考试常见的做法是:在程序开头给定random.seed(x)这样的固定种子(评卷时侯的测试用例里有指定),然后你后面的代码在同一个种子的约束下输出结果应该是确定的。这就意味着代码逻辑必须严格按评卷程序期望的调用顺序来写,不能随意在中间多加一次random调用——你多调用一次,序列就整体往后跳一格,最终结果就和答案对不上了。这个坑我在第4节会展开讲。

3. 随机种子与伪随机原理:理解这个,很多选择题就不用背

random库考来考去,绕不开"伪随机"这三个字。如果你只记函数签名而不理解伪随机机制,遇到稍微变形的题目就会懵;理解了机制以后,那些选择题基本就是送分题。

3.1 为什么是"伪随机"而不是"真随机"

计算机里的标准库random本质上是确定性算法:它从初始种子出发,通过一个递推公式不断生成看起来杂乱无序、但规律完全确定的数。也就是说,只要种子固定,生成的数列在世界任何一台电脑上都是一样的(除非Python版本不同)。这个数列在统计学上具有良好的均匀性和独立性,足以模拟日常场景里的随机需求,所以叫"伪随机"。

我在给初学者讲这个概念时经常用这样一个比喻:伪随机数生成器就像一本有十万页的"乱数表",种子决定了翻开第几页;从这一页开始,每往后读一行就是一个"随机数"。同一页开头读出来的序列永远一样。你做实验时设定random.seed(42),就相当于告诉程序"从第42页开始读"。

理解这一点对考试的意义是什么?

  • 选择题里如果问"random库的随机数是真随机还是伪随机",答案一定是伪随机;
  • 如果问"种子相同则随机序列是否相同",答案是一定相同;
  • 如果问"random.seed()不带参数会怎样",答案是基于当前系统时间等随机源来自动生成种子,每次运行序列完全不同。

这些考点不用背,理解了机制自然就能选对。

3.2 种子在二级上机考试中的隐藏作用

二级Python的上机编程题有一部分是结果可验证的,这就要求考生的程序在给定的输入条件下必须产生确定输出。如果题目里用自己的随机过程而不设种子,不同考生会得到不同结果,评卷就没法统一了。所以历年真题里,只要程序设计题涉及到随机,几乎都会在题目开头或者题目叙述中给出种子设置:

例如某年真题模拟"大乐透号码生成",题目会写"在某行代码中设置随机种子为N"之类的提示。这时候你务必要在同一位置调用random.seed(N),并且保持后面的random方法调用顺序和官方标准答案一致。

这里要强调一个我见过的经典翻车案例:程序里需要生成5个随机数和1个额外随机数,有的考生先把5个数放循环里调用了5次randint,出来后又额外调用了1次random()来生成小数——但由于多加的这次调用改变了后续随机序列,前面的5个数已经变了。如果评卷程序是按"连续调用6个特定函数后比对结果"来判分的,这种代码分数就会被扣掉。

所以在写调用了random库的编程题时,需要遵循一个纪律:先规划好一共要调用几次random函数、以什么顺序调用,然后一次也不要多、一次也不少地写完。平时练习时养成这个习惯,上机才稳定。

3.3 从源码层面看一眼生成器:Mersenne Twister的"考试友好"特性

random库的默认生成器是Mersenne Twister(梅森旋转算法)。它的周期长达2的19937次方减1,分布均匀性和随机性都很好,而且算法实现高效、稳定。二级考试不会让你实现这个算法,但你至少要知道一件事:Mersenne Twister的输出质量足以模拟抛硬币、掷骰子、随机抽样这些日常随机场景,所以考试程序里的随机结果即使不设定种子,单独看也是"够随机"的。这给考生的启发是——在不需要复现结果的普通练习题里,你可以放心使用random库做模拟实验,不用担心输出分布明显偏差。

不过有一个小细节注意一下:Python 3.9之后,random.shuffle等函数内部实现有微小变化,但考试环境一般固定某个Python版本(通常是3.8或3.9),所以实际运行结果和评卷基准一致即可,不要在你的本地用新版本Python强行对齐某道真题的输出,容易出偏差。平时练习建议直接使用与考试环境相近的Python版本。

4. 历年真题高频题型与可直接抄用的代码模板

接下来这部分是实战环节。我结合自己在备考和辅导过程中反复遇到的高频题型,整理出几个可以直接背下来、考试时改改参数就能用的代码模板。建议每段代码都亲手敲一遍,别只是看。

4.1 模板一:随机验证码生成(字符串与random的经典组合)

生成n位随机验证码是二级考试老熟人,最常见的是生成四位、六位由数字加字母组成的验证码。

import random import string def generate_code(length=6): # 数字 + 大写字母 + 小写字母 chars = string.ascii_letters + string.digits code = "".join(random.choices(chars, k=length)) return code random.seed(2025) print(generate_code(6))

这个模板用到了random.choices的k参数,一次性抽取length个字符,再用字符串的join拼起来。注意如果把choices换成sample,验证码里就不可能出重复字符;用choices则允许重复。题目要求"可重复"还是"不可重复"要看清,一字之差逻辑完全不同。

如果题目要求不使用string模块,也可以自己定义字符池:

import random def generate_code(length=4): chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" code = "".join(random.choice(chars) for _ in range(length)) return code

这里用到了生成器表达式,每循环一次取一个字符,取length次。两种写法都要会,尤其是第二种在考试环境里更稳——因为有的考场可能不允许导入string模块(其实标准库允许,但为了稳妥,会手写字符池更好)。我自己更喜欢第一种,因为它简洁,但教学生时我会强调第二种的容错性。

4.2 模板二:随机抽样与分组(sample和shuffle的应用)

抽样类题目在二级里经常伪装成"随机抽取几个幸运观众""随机分组""随机抽取若干题重做"等场景。核心区分在于:要不要重复、要不要改变原本顺序。

不需要重复,且不改变原列表 -> 用sample:

import random students = [f"学生{i}" for i in range(1, 31)] random.seed(5) # 从30人中不重复抽取5人 winners = random.sample(students, 5) print(winners)

需要把顺序完全打乱(比如分组前洗牌)-> 用shuffle:

import random students = [f"学生{i}" for i in range(1, 31)] random.seed(5) random.shuffle(students) # 打乱后第1组取前10人,第2组取下10人,第3组取最后10人 group1 = students[:10] group2 = students[10:20] group3 = students[20:] print(group1, group2, group3, sep="\n")

注意用shuffle时原students列表已经被修改了,所以group1、group2、group3里的人是互不重复且恰好覆盖全体的。有些同学喜欢用sample(students, 10)重复抽三次来分三组,这种方式在逻辑上是错的,因为sample每调用一次都是独立抽样,三组之间可能有人重复。

4.3 模板三:掷骰子、抛硬币等蒙特卡洛模拟

模拟类程序题通常要你统计大量随机实验的结果频率,核心套路是循环+计数。

import random random.seed(42) # 统计掷骰子10000次,各点数出现的次数 counts = [0] * 7 # 下标0不用,1~6对应用点数 for _ in range(10000): point = random.randint(1, 6) counts[point] += 1 for i in range(1, 7): print(f"点数{i}:{counts[i]}次,概率{counts[i]/10000:.4f}")

这里[0] * 7是二级备考里非常实用的初始化技巧——需要统计1到6的点数,列表长度开7个,下标0白白空着,让下标和点数一一对应。很多新手喜欢用[0, 0, 0, 0, 0, 0, 0]写7个0,效果一样,但前者更简洁。

抛硬币统计正面次数的模板更有代表性:

import random random.seed(100) n = 1000 heads = 0 for _ in range(n): if random.random() < 0.5: heads += 1 print("正面次数:", heads) print("正面概率:", heads / n)

值得注意的是:判断条件写random.random() < 0.5还是<= 0.5,理论上会略微影响结果(差异极小,单次运行看不出来),但在考试中你只需要保证逻辑自洽即可。评卷通常考察算法思想,而不是精确到某一次随机的结果,除非题目指定种子并要求完全一致的输出。

4.4 模板四:经典游戏化题目"猜数字"

猜数字几乎每年都会以某种姿态出现在二级复习资料里。它同时考察randint(生成目标数字)、循环(反复猜测)、条件判断(猜大猜小)。

import random random.seed(88) target = random.randint(1, 100) guess = -1 count = 0 while guess != target: guess = int(input("请输入你猜的数字(1~100):")) count += 1 if guess > target: print("猜大了") elif guess < target: print("猜小了") else: print(f"恭喜!你用了{count}次猜中")

程序题中如果出现input(),你在本地测试时要手动输入数字,比较麻烦;有些模拟软件能自动输入。我更推荐的练习方式是预先构造一个猜数列表来模拟用户输入,比如for g in [50, 25, 80, 71]:,这样可以避免反复手动敲键盘。

这个模板看起来简单,但它有一个很多考二级的同学会忽略的考点:randint(1, 100)的取值范围是1到100闭区间,如果题目要求"随机生成一个1到99之间的整数",就必须用randrange(1, 100)才行。一字之差,答案边界完全不同。

4.5 模板五:随机密码生成与字符池权重定制

如果题目要求生成带一定规则的密码,比如"必须包含至少一个大写字母、一个小写字母和一个数字",只靠一个choices就不够严谨,需要分步保证:

import random import string def strong_password(length=8): lower = random.choice(string.ascii_lowercase) # 保证有1个小写 upper = random.choice(string.ascii_uppercase) # 保证有1个大写 digit = random.choice(string.digits) # 保证有1个数字 remaining = "".join(random.choices(string.ascii_letters + string.digits, k=length-3)) # 把4部分拼起来后打乱顺序,避免"大写字母永远在开头"这种规律性 password_list = list(lower + upper + digit + remaining) random.shuffle(password_list) return "".join(password_list) random.seed(7) print(strong_password(8))

这里最容易被忽略的点是最后一步shuffle。如果不打乱,生成的密码永远是"小写+大写+数字+随机字符"这个固定结构,题目一旦要求"随机排列"就得不到满分。把字符串拆成列表、shuffle、再拼接,是二级考试里"字符串+random"组合题的万能收尾操作。记住这个三步走:list()->shuffle->"".join()。

5. 上机实战:环境准备、典型报错与得分细节

会写代码模板只是第一步,上机考试时能否顺利运行、能否拿全分,还取决于一些很容易被忽略的细节。我这部分把实际练习时的经验浓缩起来,按"考前准备 -> 调试排错 -> 检查提分"三个阶段来梳理。

5.1 考场环境与本地练习环境的一致性

计算机二级Python考试的环境通常是Windows系统上的Python 3.8或3.9(不同考区可能略有差异),考试系统自带IDLE或者特定的考试客户端。你在自己电脑上练习时,建议提前确认:

  • Python版本:尽量装3.8或3.9,不要用Python 3.12/3.13这种很新的版本。新版本虽然语法向下兼容,但某些标准库的随机序列生成细节若有微调,可能导致真题输出难以复现。
  • 不需要额外安装任何第三方库:random是标准库,二级考试范围也只考标准库,考试机器上不会给你装numpy、pandas这些东西。平时练习如果装了Anaconda,要注意别在代码里顺手import不在考纲内的模块。
  • 中文编码:上机考试环境可能涉及文件读取,如果代码里出现中文字符串,务必保证文件头有# -*- coding: utf-8 -*-或确保编辑器默认UTF-8。有些考场客户端默认编码不是UTF-8,会导致读取含中文的文本文件时报UnicodeDecodeError。

用本地命令行验证一下环境:

python --version python -c "import random; print(random.randint(1,10))"

两条命令能正常输出,说明random库没问题,可以拿真题开练。

5.2 经典报错场景与修复:实战排错清单

我在辅导过程中见过大量新手在上机时反复报错的场景,集中列出来,每个都是真实的坑:

场景一:TypeError: 'NoneType' object is not iterable / 对shuffle结果继续操作

import random lst = [1, 2, 3, 4, 5] new_lst = list(range(len(lst))) # 错误示范 # 先写 new_list = random.shuffle(lst) # 然后又遍历 new_list,结果 new_list 是 None —— 报错!

修复方式在第2.4节已经说过:shuffle是原地操作,重新赋值给变量会拿到None。要么直接使用原列表,要么先复制再shuffle。

场景二:IndexError: Cannot choose from an empty sequence

import random empty = [] print(random.choice(empty)) # 报错:IndexError

choice要求序列非空。考试题里如果从一个筛选后的列表里抽元素,先判断len(lst) > 0再加choice,否则遇到空列表就崩。这个坑常在"从符合某种条件的数据里随机抽一个"的题目里出现。

场景三:ValueError: Sample larger than population or is negative

import random lst = [1, 2, 3] print(random.sample(lst, 5)) # 报错:样本数超过总体数

sample的k不能大于序列长度(不允许重复抽取的前提下)。如果题目要求"可能有重复地抽5个",就改用choices;如果题目要求"不重复地抽5个但序列只有3个元素",必须在抽取前扩容序列或改换思路。

场景四:因为随机种子设置时机不对导致结果不对

import random print(random.randint(1, 100)) # 第一次调用 random.seed(10) # 种子设在调用之后,前面已经产生随机数,种子对它无效 print(random.randint(1, 100)) # 这已经是种子的第一个随机数

很多考生习惯在程序中间任何位置写random.seed(10),导致面对真题时前面已经消费了几个随机数、后面结果对不上。正确做法是:一旦题目指定种子,程序开头、所有random调用之前先执行seed,确保第一个随机数就是评卷程序期望的第一个随机数。

5.3 考试检查清单:交卷前5分钟该看什么

上机考试时间紧凑,但交卷前留几分钟检查random相关代码绝对值得。我把检查要点列成清单,你可以对照自查:

  • [ ] 是否在所有random调用之前设置了seed(如果题目要求)?
  • [ ] 程序中random调用次数是否和标准思路一致?有没有多写或少写?
  • [ ] 使用shuffle后是否误用返回值?是否正确操作了原列表?
  • [ ] 使用sample抽取的k是否不大于序列长度?
  • [ ]randint的右边是闭区间,确认题目要的是闭还是开;如需要开区间请改用randrange。
  • [ ] 字符串拼接随机字符时,字符是否先转成str类型?特别是用choice选出的数字,直接拼接会报TypeError。
  • [ ] 如果用了input(),输入的数据是否做了int类型转换?
  • [ ] 程序有无额外导入非标准库模块?

其中第六点特别值得展开提醒:用random.choice("0123456789")选出来的是字符'5',直接拼接没问题;但如果用random.randint(0, 9)选出来的是整数5,直接拼字符串就会报错。正确写法是str(random.randint(0, 9))。这个细节至少值一分。

5.4 一个完整的交叉综合例题:真题级别的实战演练

为了把上面的知识点串起来,我最后给出一道和真题难度相当的综合性练习题,建议你先自己写一遍,再对照我的参考实现。

题目:模拟一次年会抽奖程序。参加人数共50人,编号从1到50。要求:

  1. 先随机选出3名三等奖;
  2. 再从剩下的人中随机选出2名二等奖;
  3. 最后从剩余的人中选出1名一等奖;
  4. 输出每个奖项的中奖编号。

核心考点:sample不重复抽取的特性、seed的设定、列表差集操作。

参考实现:

import random random.seed(2025) people = list(range(1, 51)) third = random.sample(people, 3) # 三等奖:3人 # 从原列表中移除三等奖获得者 remaining = [p for p in people if p not in third] second = random.sample(remaining, 2) # 二等奖:2人 # 再移除二等奖获得者 remaining = [p for p in remaining if p not in second] first = random.sample(remaining, 1) # 一等奖:1人 print("三等奖:", third) print("二等奖:", second) print("一等奖:", first)

这里面用列表推导式做差集是最直观的解法。你可能会想到用set去重后再sample,但set会把顺序打乱,而且不同Python版本下set迭代顺序可能不同,会影响seed复现,所以不推荐。

这道题考察的正是random库+列表操作的组合能力:sample每次都在原序列上做不重复抽取,因此只要每轮更新剩余人员列表,逻辑就不会乱。如果误用choice或choices,中奖编号大概率会重复,整道题覆灭。

6. 备考期间刷random题的三个心得

最后聊点备考策略以外的体会,算是我自己练习random相关真题时总结出的几个"非技术"经验。

第一,不要死记函数官方文档,而是把所有函数的边界条件画成一张小卡片。我的卡片上就写着一句话:random()半开区间,randint闭区间,randrange开区间+步长,choice返回单值,choices返回列表(k默认为1),sample不重复返回新列表,shuffle原地返回None。考试前翻一眼,比翻一小时文档管用。

第二,遇到真题里的random题,一定要动手敲一遍而不是只看答案。因为random类题目的"程序填空"往往考察你能否理解代码在若干次调用之后的状态——只看答案你永远不知道shuffle返回None这个坑会导致什么,也不知道多调用一次random会把整个序列推到哪里去。哪怕只是把答案代码抄一遍然后运行一下,你对"随机序列的推进感"都会比纯阅读深刻得多。

第三,上机练习时尽量给自己设定"禁看答案"的模拟条件。我备考时规定自己每道题先花10分钟独立完成,再对照标准答案。错得越多,印象越深。尤其是那种"老觉得自己写对了,结果输出和答案差一点"的情况,基本都能定位到random调用次数或边界范围上——这些错题记录,就是考前一周最宝贵的复习资料。

希望这篇梳理能帮你把random库这块的分数稳稳攥在手里。计算机二级的题目其实并不难,难的是细心和边界感。把上面这些容易踩的坑挨个排掉,random相关的内容在考场上对你来说就只剩下"套模板"这一件事了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/9 18:46:42

MATLAB圆孔菲涅尔衍射仿真:从原理到代码实现与避坑指南

1. 从一次仿真翻车说起&#xff1a;为什么要啃圆孔菲涅尔衍射几年前帮一个做光学检测的朋友复现一个孔径衍射实验&#xff0c;他信誓旦旦地说“近场衍射嘛&#xff0c;套个夫琅禾费公式就完事了”&#xff0c;结果仿真出来的光斑和实验拍到的完全对不上——实验图中心亮斑周围有…

作者头像 李华
网站建设 2026/10/9 18:41:04

凸分析工具链:示性函数、共轭函数与对偶范数实战指南

1. 从示性函数到共轭函数&#xff1a;一套被低估的凸分析工具链示性函数、共轭函数、对偶范数、共轭——这四个词放在一起&#xff0c;很多人第一反应是“凸优化课本里的东西&#xff0c;考试完就还给老师了”。但我自己做过几个涉及稀疏建模和正则化求解的项目之后&#xff0c…

作者头像 李华
网站建设 2026/10/9 18:40:40

HTML练手全攻略:从骨架到天气卡片,避开新手五个坑

1. HTML 练手第一步&#xff1a;把文档骨架写进肌肉记忆 HTML 这个东西&#xff0c;跟我刚开始学的时候一样&#xff0c;很多人第一反应就是"这有什么好练的&#xff1f;不就是几个标签吗&#xff1f;"但真正的问题是&#xff1a;标签认得&#xff0c;页面写不好。我…

作者头像 李华
网站建设 2026/10/9 18:36:57

Cursor 扩展工具 Context7 MCP 接入 TaoToken 的配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/9 18:35:09

Fluent Meshing水密工作流中Add Local Sizing实战指南

如果你和我一样&#xff0c;每天要和 Fluent Meshing 打交道&#xff0c;那你一定遇到过这种场景&#xff1a;全局尺寸给到0.5mm&#xff0c;算下来网格量五百多万&#xff0c;看起来数值也没问题&#xff0c;但一到弯管处&#xff0c;边界层一拉&#xff0c;圆弧面网格完全看不…

作者头像 李华