Python 教程 16:数据结构综合实战

“纸上得来终觉浅,绝知此事要躬行。”

学习了列表、元组、字典、集合后,让我们通过一个实际项目——学生成绩管理系统,把这些知识串起来,体会如何选择和组合不同的数据结构。

1. 项目需求

开发一个学生成绩管理系统,功能包括:

  1. 添加学生信息
  2. 录入和修改成绩
  3. 查询学生成绩
  4. 统计分析(平均分、最高分等)
  5. 筛选功能(如成绩优秀的学生)

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}

选择依据

  1. 科目名和分数是映射关系
  2. 需要通过科目名快速查找成绩
  3. 科目数量可能变化

何时用集合

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. 扩展功能

可以继续添加:

  1. 数据持久化:保存到 JSON 文件
  2. 批量导入:从 CSV 文件导入
  3. 数据导出:生成报表
  4. 图表展示:使用 matplotlib 绘图
  5. Web 界面:使用 Flask 搭建网页

7. 小结

这个项目综合运用了:

  • 字典:存储学生信息、成绩映射
  • 列表:存储多个对象、排序
  • 集合:去重、获取唯一值
  • 元组:返回多个值

选择原则

  • 映射关系 → 字典
  • 有序序列 → 列表
  • 去重/集合运算 → 集合
  • 多个返回值 → 元组

练习题

  1. 添加删除学生功能
  2. 实现成绩排名功能
  3. 添加数据保存/加载功能(JSON)

本文代码示例

关注公众号:极客老墨

更多 AI 应用开发、工程实践和效率工具分享,欢迎扫码关注。

极客老墨微信公众号二维码

相关阅读