Python set函数结合for/in迭代器的工作机制及示例代码解析
Python 第二低成绩查询代码运行原理解析
题目目标:输出班级内成绩为第二低的学生姓名,若存在多名符合条件的学生,需将姓名按字母序排序后逐行打印。
本次用到的示例学生数据如下:
students = [['Harry', 37.21], ['Berry', 37.21], ['Tina', 37.2], ['Akriti', 41], ['Harsh', 39]]
示例中最低分属于Tina(37.2),第二低分属于Harry和Berry(37.21),按字母序排序后应逐行输出Berry、Harry。
代码逐段逻辑拆解
1. 成绩表构建
marksheet = [] for _ in range(0,int(input())): marksheet.append([input(), float(input())])
- 首先读取输入的学生总人数,循环对应次数
- 每次循环依次读取学生姓名、读取成绩并转为浮点数,将
[姓名, 成绩]格式的二元列表存入marksheet成绩表。如果直接使用示例数据赋值,marksheet的内容和上述students列表完全一致。
2. 列表推导式的迭代解包逻辑
你提到无法理解[marks for name, marks in marksheet]的运行逻辑,这里核心是Python对可迭代对象的自动解包特性:
marksheet中存储的每个元素都是固定长度为2的列表,结构统一为[姓名字符串, 成绩浮点数]- 遍历
marksheet时写for name, marks in marksheet,等价于每次拿到单个学生的二元列表后,自动把第一个元素(姓名)赋值给name,第二个元素(成绩)赋值给marks,不需要手动通过[0]/[1]索引取值 - 整个列表推导式的作用是遍历成绩表,提取所有学生的成绩组成纯成绩列表。用示例数据运行时,该推导式的输出结果为
[37.21, 37.21, 37.2, 41, 39]
3. 第二低分的计算流程
第二低分的计算由如下代码完成:
second_highest = sorted(list(set([marks for name, marks in marksheet])))[1]
执行步骤按顺序依次为:
- 将提取到的全量成绩列表传入
set(),利用集合自动去重的特性过滤重复分数,示例数据去重后得到的集合内容为{37.21, 37.2, 41, 39} - 通过
list()将去重后的集合转为普通列表,满足后续排序、索引取值的要求 - 调用
sorted()对去重后的成绩列表做升序排列(从小到大),示例数据排序结果为[37.2, 37.21, 39, 41] - Python列表索引从0开始计数,索引
0对应最低分37.2,取索引1的元素即可得到第二低的成绩37.21,将该值存入second_highest变量
注:此处变量名
second_highest属于命名失误,实际存储的是第二低的成绩,不要被变量名误导。
4. 结果筛选与输出
最后一行代码负责筛选符合条件的学生并按要求输出:
print('\n'.join([a for a,b in sorted(marksheet) if b == second_highest]))
执行逻辑如下:
- 先对
marksheet整体排序:由于每个学生列表的第一个元素是姓名,Python对嵌套列表排序时默认优先按第一个元素的升序排列(字符串默认按字母序排序),第一个元素相同时才会比较第二个元素,刚好符合题目要求的姓名字母序排序规则 - 遍历排序后的成绩表,同样用自动解包逻辑将每个学生的姓名赋值给
a、成绩赋值给b,通过if b == second_highest过滤出所有成绩等于第二低分的学生姓名,示例数据筛选后得到的姓名列表为['Berry', 'Harry'] - 用
'\n'.join()将姓名列表用换行符拼接为单个字符串,打印后即可实现逐行输出姓名的效果,最终运行结果和预期一致:
Berry Harry
内容的提问来源于stack exchange,提问作者Aman Gupta
相关产品推荐
相关产品推荐

