前言
学生成绩管理系统通过控制台菜单与用户交互,需要支持添加、修改、删除、按姓名查询和展示全部五个功能。实现拆成 Student 和 StudentManager 两个类:前者封装单个学生的数据和成绩修改,后者封装全部操作和菜单循环。
一、功能需求与整体设计
系统一共五项功能:添加学生成绩(录入姓名和三科成绩记录到系统)、修改学生成绩(按姓名修改对应成绩)、删除学生成绩(按姓名删除)、查询指定学生成绩(按姓名查找并输出)、展示全部学生成绩。
设计上拆成两个类,按职责分工:
- Student 管"一个学生":姓名和三科成绩属于学生自己,修改成绩也是学生自身的行为,全部放进 Student;
- StudentManager 管"所有学生":学生存在哪里、怎么找、怎么增删改查,是"一组对象"的事,全部放进 StudentManager,菜单循环也由它负责。
两个类通过方法调用连接:管理类的方法内部创建、查找、修改 Student 对象。数据保存在内存的列表里,程序退出即清空,这是这个控制台版本的范围。
二、Student 类:封装单个学生的信息
python
# ============================ 学生类(封装单个学生的信息) ============================
class Student:
def __init__(self, name, chinese, math, english):
self.name = name
self.chinese = chinese
self.math = math
self.english = english
def __str__(self):
return (f"姓名:{self.name},语文:{self.chinese},"
f"数学:{self.math},英语:{self.english}")
# 修改学生成绩
def update_scores(self, chinese, math, english):
# 更新学生的三科成绩
self.chinese = chinese
self.math = math
self.english = english
构造方法的四个参数在实例化时传入,依次挂到 self 上,一个 Student 对象就是一个学生的完整档案。__str__ 定义了 print(学生对象) 时的输出格式,两行 f-string 用括号拼接成一个完整字符串,避免一行写太长。update_scores 接收新的三科成绩,逐个覆盖 self 上的旧值,参数名和属性名同名,self.chinese = chinese 左边是属性、右边是参数,语义清楚。
三、StudentManager 类:封装全部操作
1. 数据载体与查找辅助方法
python
# ============================ 教务管理系统类(封装所有操作) ============================
class StudentManager:
def __init__(self):
# 用列表保存所有学生对象
self.students = []
# ---------- 辅助方法:根据姓名查找学生对象 ----------
def find_student(self, name):
for student in self.students:
if student.name == name:
return student
return None # 没找到返回 None
students 列表是系统唯一的存储位置,后面所有功能都围绕它读写。find_student 遍历列表,按姓名逐个匹配,找到就返回学生对象,走完全列表没命中就返回 None。返回 None 是这个方法的约定,后面的添加、修改、删除、查询拿到结果后只需判断两种情况:是对象就操作,是 None 就提示。
2. 添加学生成绩
python
# ---------- 1. 添加学生成绩 ----------
def add_student(self):
name = input("请输入学生姓名:")
# 先判断学生是否已存在,避免重复添加
if self.find_student(name):
print("该学生已存在,请勿重复添加 ~")
return
chinese = int(input("请输入语文成绩:"))
math = int(input("请输入数学成绩:"))
english = int(input("请输入英语成绩:"))
# 创建学生对象并加入列表
if 0 <= chinese <= 100 and 0 <= math <= 100 and 0 <= english <= 100:
student = Student(name, chinese, math, english)
self.students.append(student)
print("学生信息添加完毕 ~")
else:
print("存储失败")
添加做两道校验:先用 find_student 查重,已存在直接 return,此时三科成绩还没录入,用户不会白输一串分数;三科成绩用 int() 转成整数后,检查是否都在 0 到 100 之间,三科用 and 连接,任何一科越界都不会添加。两道校验都通过,才创建 Student 对象并 append 进列表。
3. 修改学生成绩
python
# ---------- 2. 修改学生成绩 ----------
def modify_student(self):
name = input("请输入要修改的学生姓名:")
student = self.find_student(name)
if student:
# 录入新的三科成绩并更新
chinese = int(input("请输入新的语文成绩:"))
math = int(input("请输入新的数学成绩:"))
english = int(input("请输入新的英语成绩:"))
student.update_scores(chinese, math, english)
print("学生信息修改完毕 ~")
else:
print("该学生不存在,请重新选择 ~")
修改的核心调用是 student.update_scores(chinese, math, english):管理类先找到学生,再把新成绩交给学生自己的方法去更新,管理类不用直接碰成绩字段。if student 一个判断覆盖两种情况,找到就走录入和更新,None 就提示不存在。
4. 删除、查询和展示全部
python
# ---------- 3. 删除学生成绩 ----------
def delete_student(self):
name = input("请输入要删除的学生姓名:")
student = self.find_student(name)
if student:
self.students.remove(student)
print("学生信息删除完毕 ~")
else:
print("该学生不存在,请重新选择 ~")
# ---------- 4. 查询指定学生成绩 ----------
def query_student(self):
name = input("请输入要查询的学生姓名:")
student = self.find_student(name)
if student:
# __str__ 已定义,直接打印对象即可
print(student)
else:
print("该学生不存在,请重新选择 ~")
# ---------- 5. 展示全部学生成绩 ----------
def show_all_students(self):
if not self.students:
print("系统中暂无学生信息 ~")
return
# 遍历学生列表,输出每个学生的信息
for student in self.students:
print(student)
删除先用 find_student 拿到对象,再用列表的 remove(student) 按对象删除,比按下标删安全,删不存在的人也不会出问题。查询和展示都直接 print(student),输出格式完全由 Student 的 __str__ 决定,管理类不需要重复拼成绩字符串。show_all_students 先用 not self.students 判断空列表,空就提示后 return,有数据再遍历逐个打印。
四、菜单循环与程序入口
python
# ---------- 主菜单循环 ----------
def run(self):
while True:
print("\n========== 学生成绩管理系统 ==========")
print("1. 添加学生成绩")
print("2. 修改学生成绩")
print("3. 删除学生成绩")
print("4. 查询指定学生成绩")
print("5. 展示全部学生成绩")
print("0. 退出系统")
print("======================================")
choice = input("请输入你的选择:")
if choice == "1":
self.add_student()
elif choice == "2":
self.modify_student()
elif choice == "3":
self.delete_student()
elif choice == "4":
self.query_student()
elif choice == "5":
self.show_all_students()
elif choice == "0":
print("感谢使用,再见 ~")
break
else:
print("输入有误,请重新选择 ~")
# ============================ 程序入口 ============================
if __name__ == "__main__":
manager = StudentManager() # 创建教务管理系统对象
manager.run() # 启动系统
run 是整个系统的调度中心:while True 让菜单反复出现,每轮先打印菜单再读一次输入;input 返回的是字符串,所以 choice 直接和 "1" 到 "5"、"0" 这些字符串比较;命中哪个分支就调用对应的功能方法,执行完回到下一轮菜单。输入 0 时 break 跳出循环,系统结束;其他非法输入走 else 提示,不影响循环继续。
程序入口两行只在直接运行这个文件时执行------此时 __name__ 等于 __main__,创建一个 StudentManager 对象并调用 run,系统启动。文件被当作模块导入时这段不执行,菜单循环不会误启动。
五、验证方式与易错点
按这个顺序操作一遍,就能覆盖全部功能:运行脚本进入菜单 → 选 1 添加一个学生,三科成绩都输 0 到 100 之间的数,提示添加完毕 → 再选 1 输入同名姓名,应提示已存在;输入越界成绩(比如 101),应提示存储失败 → 选 4 输入刚添加的姓名,打印出三科成绩 → 选 2 修改三科成绩,再选 4 查询,应看到新成绩 → 选 5 展示全部,列表里能看到这个学生 → 选 3 删除后再选 4,应提示不存在 → 选 0 退出系统。
两个易错点:
- int(input()) 遇到非数字输入会直接崩溃。添加或修改时把成绩输成"九十分"这样的文本,int() 转换抛 ValueError,程序当场退出。改进方向是用 try/except 包住转换,捕获异常后提示重新输入。
- 同名学生会命中第一个。find_student 按姓名匹配,列表里有同名学生时返回靠前的那个,修改和删除只会作用在它身上。真实系统里应该用学号这类唯一标识来定位。
六、总结
这篇用两个类完成控制台版学生成绩管理系统:Student 只负责一个学生的数据和改成绩,StudentManager 持有列表、负责全部操作和菜单分发,五个功能全部从 find_student 起步。可迁移的判断是:写这类管理型程序时,把单个对象自身的行为和对一组对象的操作拆进两个类,操作前统一走一个查找方法,功能方法之间就不会堆满重复的遍历和判断。