太棒了!欢迎来到 【跟着AI学Python】第21天 —— 复习 + 实战小项目日!🎉我们将综合运用 OOP(类)、文件操作、列表/字典、异常处理 等前20天所学,开发一个 学生成绩管理系统!
💡 本项目目标:✅ 使用 类封装 学生和成绩管理逻辑✅ 支持 添加学生、录入成绩、计算平均分✅ 数据 保存到 students.json(持久化)✅ 提供 清晰的命令行交互界面
🎯 功能需求
📁 文件结构
student_manager/├── student_system.py ← 主程序└── students.json ← 自动生成的学生数据文件
🔧 完整代码:student_system.py
# student_system.pyimport jsonimport osfrom typing import Dict, ListDATA_FILE = "students.json"class Student: """学生类""" def __init__(self, name: str, scores: Dict[str, float] = None): self.name = name self.scores = scores or {} # {"数学": 95, "英语": 88} def add_score(self, subject: str, score: float): """录入成绩""" if not (0 <= score <= 100): raise ValueError("成绩必须在 0-100 之间") self.scores[subject] = score def average_score(self) -> float: """计算平均分""" if not self.scores: return 0.0 return round(sum(self.scores.values()) / len(self.scores), 2) def to_dict(self) -> dict: """转换为字典(用于 JSON 序列化)""" return { "name": self.name, "scores": self.scores } @classmethod def from_dict(cls, data: dict): """从字典创建 Student 对象""" return cls(name=data["name"], scores=data["scores"]) def __str__(self): avg = self.average_score() scores_str = ", ".join(f"{k}: {v}" for k, v in self.scores.items()) return f"姓名: {self.name} | 成绩: {scores_str} | 平均分: {avg}"class StudentManager: """学生成绩管理系统""" def __init__(self): self.students: Dict[str, Student] = self.load_students() def load_students(self) -> Dict[str, Student]: """从 JSON 文件加载学生数据""" if not os.path.exists(DATA_FILE): return {} try: with open(DATA_FILE, "r", encoding="utf-8") as f: data = json.load(f) return {name: Student.from_dict(student_data) for name, student_data in data.items()} except (json.JSONDecodeError, IOError) as e: print(f"⚠️ 警告:无法读取数据文件,使用空数据。错误: {e}") return {} def save_students(self): """保存学生数据到 JSON 文件""" try: with open(DATA_FILE, "w", encoding="utf-8") as f: json.dump( {name: student.to_dict() for name, student in self.students.items()}, f, ensure_ascii=False, indent=2 ) except IOError as e: print(f"❌ 保存失败: {e}") def add_student(self, name: str): """添加新学生""" if not name.strip(): print("❌ 姓名不能为空!") return if name in self.students: print(f"⚠️ 学生 '{name}' 已存在!") return self.students[name] = Student(name) self.save_students() print(f"✅ 学生 '{name}' 添加成功!") def add_score(self, name: str, subject: str, score: float): """为学生录入成绩""" if name not in self.students: print(f"❌ 学生 '{name}' 不存在!请先添加学生。") return try: self.students[name].add_score(subject, score) self.save_students() print(f"✅ {name} 的 {subject} 成绩已录入: {score}") except ValueError as e: print(f"❌ 录入失败: {e}") def show_student(self, name: str): """显示单个学生信息""" if name not in self.students: print(f"❌ 学生 '{name}' 不存在!") return print(self.students[name]) def show_all_students(self): """显示所有学生及平均分""" if not self.students: print("📭 暂无学生数据!") return print("\n📋 所有学生成绩:") for name, student in self.students.items(): print(f"- {name}: 平均分 {student.average_score()}") print()def main(): """主程序循环""" manager = StudentManager() print("🎓 欢迎使用学生成绩管理系统!") while True: print("\n请选择操作:") print("1. 添加学生") print("2. 录入成绩") print("3. 查看学生详情") print("4. 查看所有学生") print("5. 退出") choice = input("请输入选项 (1-5): ").strip() if choice == "1": name = input("请输入学生姓名: ").strip() manager.add_student(name) elif choice == "2": name = input("请输入学生姓名: ").strip() subject = input("请输入科目: ").strip() try: score = float(input("请输入成绩 (0-100): ")) manager.add_score(name, subject, score) except ValueError: print("❌ 请输入有效的数字!") elif choice == "3": name = input("请输入学生姓名: ").strip() manager.show_student(name) elif choice == "4": manager.show_all_students() elif choice == "5": print("👋 再见!") break else: print("❌ 无效选项,请输入 1-5")if __name__ == "__main__": main()
🔍 项目亮点解析
| |
|---|
| OOP 封装 | Student管理单个学生,StudentManager 管理全局逻辑 |
| JSON 持久化 | 自动读写 students.json,重启不丢失数据 |
| 类型提示 | typing模块提升代码可读性(Python 3.5+) |
| 异常处理 | |
| 数据结构 | 用 Dict[str, Student] 快速通过姓名查找学生 |
| 平均分计算 | round(..., 2)保留两位小数 |
🧪 运行效果演示
✅ 今日小任务(可选挑战)
# ===== 在 StudentManager 类中新增以下方法 =====def delete_student(self, name: str): """删除学生(含确认)""" if name not in self.students: print(f"❌ 学生 '{name}' 不存在!") return confirm = input(f"⚠️ 确定要删除学生 '{name}' 吗?(y/N): ").strip().lower() if confirm in ('y', 'yes'): del self.students[name] self.save_students() print(f"🗑️ 学生 '{name}' 已删除!") else: print("❌ 取消删除。")def show_all_students_sorted(self): """按平均分从高到低显示所有学生""" if not self.students: print("📭 暂无学生数据!") return # 按平均分降序排序 sorted_students = sorted( self.students.items(), key=lambda item: item[1].average_score(), reverse=True ) print("\n📊 所有学生成绩(按平均分排序):") for i, (name, student) in enumerate(sorted_students, 1): print(f"{i}. {student}") print()def export_to_csv(self, filename: str = "report_card.csv"): """导出成绩单为 CSV 文件""" if not self.students: print("📭 无学生数据,无法导出!") return import csv # 获取所有科目(用于表头) all_subjects = set() for student in self.students.values(): all_subjects.update(student.scores.keys()) all_subjects = sorted(all_subjects) # 固定科目顺序 try: with open(filename, "w", newline="", encoding="utf-8-sig") as f: writer = csv.writer(f) # 写入表头 header = ["姓名"] + all_subjects + ["平均分"] writer.writerow(header) # 写入每个学生成绩 for name, student in self.students.items(): row = [name] for subject in all_subjects: row.append(student.scores.get(subject, "")) # 未修科目留空 row.append(student.average_score()) writer.writerow(row) print(f"✅ 成绩单已导出到: {filename}") except IOError as e: print(f"❌ 导出失败: {e}")

def show_all_students_sorted(self): """按平均分从高到低显示所有学生""" if not self.students: print("📭 暂无学生数据!") return # 按平均分降序排序 sorted_students = sorted( self.students.items(), key=lambda item: item[1].average_score(), reverse=True ) print("\n📊 所有学生成绩(按平均分排序):") for i, (name, student) in enumerate(sorted_students, 1): print(f"{i}. {student}") print()

def export_to_csv(self, filename: str = "report_card.csv"): """导出成绩单为 CSV 文件""" if not self.students: print("📭 无学生数据,无法导出!") return import csv # 获取所有科目(用于表头) all_subjects = set() for student in self.students.values(): all_subjects.update(student.scores.keys()) all_subjects = sorted(all_subjects) # 固定科目顺序 try: with open(filename, "w", newline="", encoding="utf-8-sig") as f: writer = csv.writer(f) # 写入表头 header = ["姓名"] + all_subjects + ["平均分"] writer.writerow(header) # 写入每个学生成绩 for name, student in self.students.items(): row = [name] for subject in all_subjects: row.append(student.scores.get(subject, "")) # 未修科目留空 row.append(student.average_score()) writer.writerow(row) print(f"✅ 成绩单已导出到: {filename}") except IOError as e: print(f"❌ 导出失败: {e}")
📝 复习:21天核心技能整合
| |
|---|
| 类与对象 | Student, StudentManager |
| 文件操作 | json.load()/ json.dump() |
| 异常处理 | try-except捕获输入错误 |
| 数据结构 | |
| 函数模块化 | |
| 用户交互 | |
🎉 恭喜完成第21天!你不仅复习了前20天的知识,还构建了一个真正实用的小型管理系统!
继续加油,你的 Python 工程能力已经非常扎实了!🚀