Python 教程 16:数据结构综合实战
“纸上得来终觉浅,绝知此事要躬行。”
学习了列表、元组、字典、集合后,让我们通过一个实际项目——学生成绩管理系统,把这些知识串起来,体会如何选择和组合不同的数据结构。
1. 项目需求
开发一个学生成绩管理系统,功能包括:
- 添加学生信息
- 录入和修改成绩
- 查询学生成绩
- 统计分析(平均分、最高分等)
- 筛选功能(如成绩优秀的学生)
2. 数据结构设计
方案选择
1# 学生信息:用字典
2student = {
3 "id": "2024001",
4 "name": "张三",
5 "age": 18,
6 "scores": { # 成绩:嵌套字典
7 "数学": 95,
8 "英语": 88,
9 "物理": 92
10 }
11}
12
13# 所有学生:用列表存储
14students = [
15 {"id": "2024001", "name": "张三", "age": 18, "scores": {"数学": 95}},
16 {"id": "2024002", "name": "李四", "age": 19, "scores": {"数学": 88}},
17]
18
19# 学号索引:用字典加速查找
20students_by_id = {
21 "2024001": students[0],
22 "2024002": students[1],
23}
3. 核心功能实现
3.1 学生管理类
1class StudentManager:
2 """学生成绩管理系统"""
3
4 def __init__(self):
5 self.students = {} # {学号: 学生信息}
6
7 def add_student(self, student_id, name, age):
8 """添加学生"""
9 if student_id in self.students:
10 print(f"学号{student_id}已存在")
11 return False
12
13 self.students[student_id] = {
14 "id": student_id,
15 "name": name,
16 "age": age,
17 "scores": {}
18 }
19 print(f"✓ 添加学生:{name}")
20 return True
21
22 def add_score(self, student_id, subject, score):
23 """添加成绩"""
24 if student_id not in self.students:
25 print(f"学号{student_id}不存在")
26 return False
27
28 self.students[student_id]["scores"][subject] = score
29 print(f"✓ 录入成绩:{subject} = {score}")
30 return True
31
32 def get_student(self, student_id):
33 """查询学生信息"""
34 return self.students.get(student_id)
35
36 def get_average(self, student_id):
37 """计算学生平均分"""
38 student = self.get_student(student_id)
39 if not student or not student["scores"]:
40 return None
41
42 scores = student["scores"].values()
43 return sum(scores) / len(scores)
44
45 def get_top_students(self, n=5):
46 """获取成绩最好的N名学生"""
47 # 计算每个学生的平均分
48 student_avgs = []
49 for sid, student in self.students.items():
50 if student["scores"]:
51 avg = sum(student["scores"].values()) / len(student["scores"])
52 student_avgs.append((student["name"], avg))
53
54 # 排序并返回前N名
55 student_avgs.sort(key=lambda x: x[1], reverse=True)
56 return student_avgs[:n]
57
58 def get_subject_stats(self, subject):
59 """统计某科目的成绩分布"""
60 scores = []
61 for student in self.students.values():
62 if subject in student["scores"]:
63 scores.append(student["scores"][subject])
64
65 if not scores:
66 return None
67
68 return {
69 "count": len(scores),
70 "max": max(scores),
71 "min": min(scores),
72 "avg": sum(scores) / len(scores)
73 }
74
75 def find_by_score_range(self, subject, min_score, max_score):
76 """查找某科目分数在指定范围内的学生"""
77 result = []
78 for student in self.students.values():
79 if subject in student["scores"]:
80 score = student["scores"][subject]
81 if min_score <= score <= max_score:
82 result.append({
83 "name": student["name"],
84 "score": score
85 })
86 return result
3.2 使用示例
1# 创建管理器
2manager = StudentManager()
3
4# 添加学生
5manager.add_student("2024001", "张三", 18)
6manager.add_student("2024002", "李四", 19)
7manager.add_student("2024003", "王五", 18)
8
9# 录入成绩
10manager.add_score("2024001", "数学", 95)
11manager.add_score("2024001", "英语", 88)
12manager.add_score("2024001", "物理", 92)
13
14manager.add_score("2024002", "数学", 87)
15manager.add_score("2024002", "英语", 94)
16manager.add_score("2024002", "物理", 89)
17
18manager.add_score("2024003", "数学", 92)
19manager.add_score("2024003", "英语", 85)
20manager.add_score("2024003", "物理", 95)
21
22# 查询学生
23student = manager.get_student("2024001")
24print(f"\n学生信息:{student['name']}")
25print(f"成绩:{student['scores']}")
26
27# 计算平均分
28avg = manager.get_average("2024001")
29print(f"平均分:{avg:.2f}")
30
31# 获取前3名
32print("\n前3名学生:")
33top_students = manager.get_top_students(3)
34for i, (name, avg) in enumerate(top_students, 1):
35 print(f"{i}. {name}: {avg:.2f}")
36
37# 统计数学成绩
38print("\n数学成绩统计:")
39stats = manager.get_subject_stats("数学")
40print(f"人数:{stats['count']}")
41print(f"最高分:{stats['max']}")
42print(f"最低分:{stats['min']}")
43print(f"平均分:{stats['avg']:.2f}")
44
45# 查找数学成绩90分以上的学生
46print("\n数学90分以上:")
47excellent = manager.find_by_score_range("数学", 90, 100)
48for item in excellent:
49 print(f"{item['name']}: {item['score']}")
4. 数据结构选择分析
为什么用字典存储学生
1# 方案1:列表(不推荐)
2students_list = [...]
3# 查找学生需要遍历:O(n)
4
5# 方案2:字典(推荐)
6students_dict = {"2024001": {...}}
7# 查找学生直接访问:O(1)
选择依据:需要频繁通过学号查找学生,字典更高效。
为什么成绩用字典
1# 成绩
2scores = {
3 "数学": 95,
4 "英语": 88
5}
选择依据:
- 科目名和分数是映射关系
- 需要通过科目名快速查找成绩
- 科目数量可能变化
何时用集合
1def get_all_subjects(self):
2 """获取所有科目"""
3 subjects = set()
4 for student in self.students.values():
5 subjects.update(student["scores"].keys())
6 return subjects
用途:自动去重,获取系统中出现过的所有科目。
5. 性能优化思路
优化 1:缓存计算结果
1class StudentManager:
2 def __init__(self):
3 self.students = {}
4 self._avg_cache = {} # 缓存平均分
5
6 def add_score(self, student_id, subject, score):
7 # 添加成绩后清除缓存
8 if student_id in self._avg_cache:
9 del self._avg_cache[student_id]
10 # ...原有逻辑
优化 2:使用索引
1# 为常用查询建立索引
2self.students_by_name = {} # {姓名: 学号}
3self.students_by_class = {} # {班级: [学号列表]}
6. 扩展功能
可以继续添加:
- 数据持久化:保存到 JSON 文件
- 批量导入:从 CSV 文件导入
- 数据导出:生成报表
- 图表展示:使用 matplotlib 绘图
- Web 界面:使用 Flask 搭建网页
7. 小结
这个项目综合运用了:
- 字典:存储学生信息、成绩映射
- 列表:存储多个对象、排序
- 集合:去重、获取唯一值
- 元组:返回多个值
选择原则:
- 映射关系 → 字典
- 有序序列 → 列表
- 去重/集合运算 → 集合
- 多个返回值 → 元组
练习题:
- 添加删除学生功能
- 实现成绩排名功能
- 添加数据保存/加载功能(JSON)
本文代码示例:
关注公众号:极客老墨
更多 AI 应用开发、工程实践和效率工具分享,欢迎扫码关注。
