代码结构构思
文件结构
student_management_system/
│
├── main.py # 主函数入口
├── manager.py # 学生管理类(增删改查功能)
└── models.py # 学生模型类
功能描述
添加学生:
- 输入学号、姓名和年龄,新增一个学生。
- 如果学号重复,则提示添加失败。
删除学生:
- 输入学号,根据学号删除学生。
- 如果学号不存在,则提示删除失败。
修改学生信息:
- 输入学号,可选择修改学生的姓名和/或年龄。
查询学生信息:
- 根据学号查找并打印学生信息。
显示所有学生:
- 列出所有学生的详细信息。
退出系统:
- 结束程序运行。
扩展建议
持久化数据:
- 使用文件(如
JSON
或CSV
)保存学生信息,退出系统时保存数据,下次运行时加载。
异常处理:
- 添加输入校验和异常捕获(如年龄输入非数字时提示用户)。
初级代码
下面是一个简单的学生管理系统的代码实现,仅仅使用面向对象实现了基本的功能
模型类:models.py
class Student: """ 学生模型类,包含学生的基本信息:姓名、年龄、学号 """ def __init__(self, student_id, name, age): self.student_id = student_id self.name = name self.age = age def __str__(self): return f"学号: {self.student_id}, 姓名: {self.name}, 年龄: {self.age}"
学生管理类:manager.py
from models import Student class StudentManager: """ 学生管理类,提供增删改查功能 """ def __init__(self): self.students = [] # 存储所有学生对象的列表 def add_student(self, student_id, name, age): """添加学生""" student = Student(student_id, name, age) self.students.append(student) print(f"添加成功: {student}") def remove_student(self, student_id): """根据学号删除学生""" for student in self.students: if student.student_id == student_id: self.students.remove(student) print(f"已删除: {student}") return print(f"学号为 {student_id} 的学生不存在") def update_student(self, student_id, name=None, age=None): """根据学号更新学生信息""" for student in self.students: if student.student_id == student_id: if name: student.name = name if age: student.age = age print(f"更新成功: {student}") return print(f"学号为 {student_id} 的学生不存在") def find_student(self, student_id): """根据学号查找学生""" for student in self.students: if student.student_id == student_id: print(f"找到学生: {student}") return student print(f"学号为 {student_id} 的学生不存在") return None def list_students(self): """列出所有学生""" if not self.students: print("当前没有学生信息") else: print("所有学生信息如下:") for student in self.students: print(student)
主函数入口:main.py
from manager import StudentManager def print_menu(): """打印菜单""" print("\n学生管理系统") print("1. 添加学生") print("2. 删除学生") print("3. 修改学生信息") print("4. 查询学生信息") print("5. 显示所有学生") print("6. 退出系统") def main(): manager = StudentManager() # 创建学生管理对象 while True: print_menu() choice = input("请选择操作(1-6): ") if choice == "1": student_id = input("请输入学号: ") name = input("请输入姓名: ") age = input("请输入年龄: ") manager.add_student(student_id, name, int(age)) elif choice == "2": student_id = input("请输入要删除的学生学号: ") manager.remove_student(student_id) elif choice == "3": student_id = input("请输入要修改的学生学号: ") name = input("请输入新姓名(可留空跳过修改): ") age = input("请输入新年龄(可留空跳过修改): ") manager.update_student(student_id, name if name else None, int(age) if age else None) elif choice == "4": student_id = input("请输入要查询的学生学号: ") manager.find_student(student_id) elif choice == "5": manager.list_students() elif choice == "6": print("退出系统") break else: print("输入有误,请重新选择!") if __name__ == "__main__": main()
添加扩展功能:
在基于基本功能的基础上,添加了持久化数据功能(使用 JSON 文件保存和加载学生信息)以及异常处理(包括输入校验和异常捕获),实现更可靠和功能完善的学生管理系统。
具体要求:
优化后的代码主要实现了以下几个功能:
- 数据持久化:
- 使用JSON文件来持久化学生数据,重新启动程序后,之前保存的学生信息仍然可以加载并使用。
StudentManager
类中添加load_students
和save_students
方法,用于在程序启动时加载数据和在退出时保存数据。
- 数据转换:
Student
类增加to_dict
和from_dict
方法,以便学生对象与JSON数据之间进行转换。
- 输入验证:
- 在
main.py
中,添加get_valid_int
函数来确保用户输入的年龄是一个有效的整数,避免程序崩溃。
- 在
- 异常处理:
- 在数据加载和保存过程中加入异常处理,确保即使数据文件不存在或者文件格式错误,程序也能继续运行。
- 在数据保存时,如果出现其他异常情况,则会输出错误信息。
- 菜单修改:
- 更新菜单中的选项:退出系统改为“保存并退出系统”,提示用户保存数据。
- 逻辑优化:
- 更新学生信息时,进行更细致的输入验证,确保输入的年龄如果为空,则不会尝试转换成整数。
持久化数据功能如何实现?
data = [student.to_dict() for student in self.students]
这段代码是一个 列表推导式(List Comprehension),用于将 self.students
(一个学生对象的列表)转换成包含学生字典的列表。下面逐步解析:
1. 基础部分:self.students
self.students
是一个存储 学生对象 的列表,例如:
self.students = [
Student("001", "Alice", 18),
Student("002", "Bob", 19)
]
这是一个包含 Student
对象的列表。
2. 调用 student.to_dict()
student.to_dict()
是一个方法,用于将 Student
对象转换为 字典。
在代码中的 Student
类里,to_dict()
可以是这样定义的:
def to_dict(self):
"""将学生对象转换为字典"""
return {"student_id": self.student_id, "name": self.name, "age": self.age}
调用 to_dict()
后,一个 Student
对象会变成这样的字典:
{"student_id": "001", "name": "Alice", "age": 18}
3. 列表推导式的作用
列表推导式将 self.students
中的每个 Student
对象转换成字典,并返回一个新列表。
代码含义:
data = [student.to_dict() for student in self.students]
等价的普通循环代码如下:
data = []
for student in self.students:
data.append(student.to_dict())
- 遍历
self.students
中的每个student
对象。 - 对每个
student
调用to_dict()
方法,生成对应的字典。 - 将所有字典组成一个新的列表,赋值给
data
示例: 假设 self.students
的内容为:
self.students = [
Student("001", "Alice", 18),
Student("002", "Bob", 19)
]
那么执行这段代码后,data
的值为:
data = [
{"student_id": "001", "name": "Alice", "age": 18},
{"student_id": "002", "name": "Bob", "age": 19}
]
这种转换通常用于 数据持久化 或 数据传输,例如:
- 将数据保存到 JSON 文件。
- 将数据发送到 API 或数据库。
如何持久化字典到json 文件中?
例如,设置在 save_students()
方法中,使用这段代码将学生对象序列化为 JSON 数据:
with open(self.DATA_FILE, "w", encoding="utf-8") as file:
data = [student.to_dict() for student in self.students]
json.dump(data, file, ensure_ascii=False, indent=4)
结果是一个 JSON 文件:
[
{
"student_id": "001",
"name": "Alice",
"age": 18
},
{
"student_id": "002",
"name": "Bob",
"age": 19
}
]
如何加载已持久化的 json 文件中的内容转化为字典列表?
要将一个已持久化的 JSON 文件加载并转化为字典列表,可以使用 Python 的 json
模块。假设你的 JSON 文件中存储的数据是一个列表,其中每个元素都是一个字典,如你所描述的结构。以下是步骤和代码示例:
- 确保 JSON 文件的结构正确,数据内容看起来应该类似于:
[
{"student_id": "001", "name": "Alice", "age": 18},
{"student_id": "002", "name": "Bob", "age": 19},
{"student_id": "003", "name": "Charlie", "age": 17}
]
- 使用 Python 代码读取文件并加载为列表:
import json
# 假设你的 JSON 文件名为 'students.json'
with open('students.json', 'r', encoding='utf-8') as file:
data = json.load(file)
# 打印加载的列表
print(data)
在这个例子中,json.load(file)
函数会读取文件内容并将其解析为字典列表。请确保在使用 open()
函数时指定正确的文件路径和编码(通常为 utf-8
,尤其是在处理可能包含非 ASCII 字符的数据时)。
这段代码,data
变量将包含文件中的数据
当然,我们可以选择优化一下代码,添加异常处理:
import json
# 假设 JSON 文件路径为 'students.json'
file_path = "students.json"
try:
# 尝试打开并读取 JSON 文件
with open(file_path, 'r', encoding='utf-8') as file:
data = json.load(file)
# 此时 data 已经是一个 Python 列表,包含字典元素
print(data)
except FileNotFoundError:
print(f"文件路径错误: {file_path} 找不到。")
except json.JSONDecodeError:
print("JSON 格式错误,无法解析文件。")
输出结果:
如何从字典转换为学生对象?
字典 转换为 Student
对象。可以使用一个 工厂方法,用来简化从外部数据结构创建 Student
实例的过程。
1. data
是什么?
data
是一个包含多个字典的列表,每个字典表示一个学生的信息。例如:
data = [
{"student_id": "001", "name": "Alice", "age": 18},
{"student_id": "002", "name": "Bob", "age": 19},
{"student_id": "003", "name": "Charlie", "age": 17}
]
2. Student.from_dict(item)
def from_dict(data):
"""从字典转换为学生对象"""
return Student(data["student_id"], data["name"], data["age"])
Student.from_dict(item)
是调用 Student
类中的静态方法,用字典 item
创建一个新的 Student
对象。假设 item
是:
{"student_id": "001", "name": "Alice", "age": 18}
则 Student.from_dict(item)
等价于:
Student("001", "Alice", 18)
3. 列表推导式
在这里:
- 表达式 是
Student.from_dict(item)
,表示将每个item
转换为Student
对象。 - 变量 是
item
,表示data
列表中的每一个字典。 - 可迭代对象 是
data
,它是包含学生数据的字典列表。
最终,这段代码会返回一个由 Student
对象组成的新列表。
4. 完整流程
- 对于
data
列表中的每个item
(即每个学生信息字典),都会调用Student.from_dict(item)
,将其转换为Student
对象。 - 生成的新
Student
对象会被收集到一个列表中。 - 最终,这个列表被赋值给
self.students
,即self.students
中存储了所有学生的对象。
我们可以先写一个简单的转化代码感受下,再带入实战:
class Student: def __init__(self, student_id, name, age): self.student_id = student_id self.name = name self.age = age @staticmethod def from_dict(data_slice): """从字典的切片中转换为学生对象""" return Student(data_slice["student_id"], data_slice["name"], data_slice["age"]) # 原始数据 data = [ {"student_id": "001", "name": "Alice", "age": 18}, {"student_id": "002", "name": "Bob", "age": 19}, {"student_id": "003", "name": "Charlie", "age": 17} ] # 转换为对象列表 students = [Student.from_dict(data_slice) for data_slice in data] print(students)
输出结果:
修改后代码内容:
1、模型类:models.py
模型类保持不变,表示学生的基本信息。
class Student: """ 学生模型类,包含学生的基本信息:姓名、年龄、学号 """ def __init__(self, student_id, name, age): self.student_id = student_id self.name = name self.age = age def __str__(self): return f"学号: {self.student_id}, 姓名: {self.name}, 年龄: {self.age}" def to_dict(self): """将学生对象转换为字典,便于持久化""" return {"student_id": self.student_id, "name": self.name, "age": self.age} @staticmethod def from_dict(data): """从字典转换为学生对象""" return Student(data["student_id"], data["name"], data["age"])
2. 学生管理类:manager.py
优化的学生管理类,支持加载和保存数据到 JSON 文件,并添加异常处理。
import json from models import Student class StudentManager: """ 学生管理类,提供增删改查功能,并支持数据持久化 """ DATA_FILE = "students.json" # 保存数据的文件路径 def __init__(self): self.students = [] # 存储所有学生对象的列表 self.load_students() # 初始化时加载数据 def load_students(self): """从文件加载学生数据""" try: with open(self.DATA_FILE, "r", encoding="utf-8") as file: data = json.load(file) self.students = [Student.from_dict(item) for item in data] print("学生数据加载成功!") except FileNotFoundError: print("数据文件不存在,已创建新的数据文件。") self.students = [] except json.JSONDecodeError: print("数据文件格式错误,已清空数据。") self.students = [] def save_students(self): """将学生数据保存到文件""" try: with open(self.DATA_FILE, "w", encoding="utf-8") as file: data = [student.to_dict() for student in self.students] json.dump(data, file, ensure_ascii=False, indent=4) print("学生数据已保存!") except Exception as e: print(f"保存数据时出现错误:{e}") def add_student(self, student_id, name, age): """添加学生""" student = Student(student_id, name, age) self.students.append(student) print(f"添加成功: {student}") def remove_student(self, student_id): """根据学号删除学生""" for student in self.students: if student.student_id == student_id: self.students.remove(student) print(f"已删除: {student}") return print(f"学号为 {student_id} 的学生不存在") def update_student(self, student_id, name=None, age=None): """根据学号更新学生信息""" for student in self.students: if student.student_id == student_id: if name: student.name = name if age: student.age = age print(f"更新成功: {student}") return print(f"学号为 {student_id} 的学生不存在") def find_student(self, student_id): """根据学号查找学生""" for student in self.students: if student.student_id == student_id: print(f"找到学生: {student}") return student print(f"学号为 {student_id} 的学生不存在") return None def list_students(self): """列出所有学生""" if not self.students: print("当前没有学生信息") else: print("所有学生信息如下:") for student in self.students: print(student)
3. 主函数入口:main.py
主函数入口中添加了异常处理和输入校验,确保系统更加稳定。
from manager import StudentManager def print_menu(): """打印菜单""" print("\n学生管理系统") print("1. 添加学生") print("2. 删除学生") print("3. 修改学生信息") print("4. 查询学生信息") print("5. 显示所有学生") print("6. 保存并退出系统") def get_valid_int(prompt): """获取有效的整数输入""" while True: try: value = int(input(prompt)) return value except ValueError: print("输入无效,请输入一个整数!") def main(): manager = StudentManager() # 创建学生管理对象 while True: print_menu() choice = input("请选择操作(1-6): ") if choice == "1": student_id = input("请输入学号: ") name = input("请输入姓名: ") age = get_valid_int("请输入年龄: ") manager.add_student(student_id, name, age) elif choice == "2": student_id = input("请输入要删除的学生学号: ") manager.remove_student(student_id) elif choice == "3": student_id = input("请输入要修改的学生学号: ") name = input("请输入新姓名(可留空跳过修改): ") age = input("请输入新年龄(可留空跳过修改): ") manager.update_student( student_id, name if name else None, int(age) if age.isdigit() else None ) elif choice == "4": student_id = input("请输入要查询的学生学号: ") manager.find_student(student_id) elif choice == "5": manager.list_students() elif choice == "6": manager.save_students() print("退出系统") break else: print("输入有误,请重新选择!") if __name__ == "__main__": main()
代码改进点总结:
持久化功能:
- 使用 JSON 文件保存和加载学生信息,退出系统时自动保存数据,下次启动时自动加载。
异常处理:
- 提供输入校验,如验证年龄是否为整数。
- 捕获文件操作中的异常(如文件不存在、JSON 格式错误)。
- 对关键逻辑的异常进行友好提示。
代码可扩展性:
Student
类支持字典与对象的转换,方便扩展到其他数据格式(如 CSV 或数据库)。- 数据文件路径
DATA_FILE
是可配置的。
优化代码算法
可以使用字典映射操作函数的方法,简化冗长的多分支 if-elif
逻辑。通过将用户输入的选项与对应的功能逻辑绑定到一个字典中,可以让代码更加简洁、清晰和易于维护。
优化后的主函数入口代码:main.py
from manager import StudentManager def print_menu(): """打印菜单""" print("\n学生管理系统") print("1. 添加学生") print("2. 删除学生") print("3. 修改学生信息") print("4. 查询学生信息") print("5. 显示所有学生") print("6. 保存并退出系统") def get_valid_int(prompt): """获取有效的整数输入""" while True: try: value = int(input(prompt)) return value except ValueError: print("输入无效,请输入一个整数!") def add_student(manager): student_id = input("请输入学号: ") name = input("请输入姓名: ") age = get_valid_int("请输入年龄: ") manager.add_student(student_id, name, age) def remove_student(manager): student_id = input("请输入要删除的学生学号: ") manager.remove_student(student_id) def update_student(manager): student_id = input("请输入要修改的学生学号: ") name = input("请输入新姓名(可留空跳过修改): ") age = input("请输入新年龄(可留空跳过修改): ") manager.update_student( student_id, name if name else None, int(age) if age.isdigit() else None ) def find_student(manager): student_id = input("请输入要查询的学生学号: ") manager.find_student(student_id) def list_students(manager): manager.list_students() def save_and_exit(manager): manager.save_students() print("退出系统") exit() def main(): manager = StudentManager() # 创建学生管理对象 actions = { "1": add_student, "2": remove_student, "3": update_student, "4": find_student, "5": list_students, "6": save_and_exit, } while True: print_menu() choice = input("请选择操作(1-6): ") action = actions.get(choice) if action: action(manager) else: print("输入有误,请重新选择!") if __name__ == "__main__": main()
优化后的特点
- 通过字典映射实现功能选择:
- 用户的输入选项(如
1
、2
、3
等)作为字典的键。 - 功能函数(如
handle_add_student
)作为字典的值。 - 根据用户输入调用字典中的对应函数,避免了大量冗长的
if-elif
逻辑。
- 用户的输入选项(如
- 功能函数独立化:
- 每个功能模块(如添加学生、删除学生等)被封装成独立的函数。
- 主函数只负责菜单显示和根据用户选择调用对应的功能函数,逻辑更加清晰。
- 支持扩展性:
- 如果需要添加新的功能,只需定义一个新的功能函数,并将其添加到
operations
字典中即可,无需修改主循环代码。
- 如果需要添加新的功能,只需定义一个新的功能函数,并将其添加到
- 代码简洁且易于维护:
- 主循环中的逻辑只有两部分:打印菜单和调用对应的功能函数。
- 函数间解耦,修改某个功能时不会影响其他功能。
字典来映射优化后续扩展功能示例
如果要新增功能,比如按年龄排序显示所有学生:
- 定义一个新的功能函数:
def handle_sort_students_by_age(manager): """按年龄排序并显示所有学生""" sorted_students = sorted(manager.students, key=lambda s: s.age) print("按年龄排序的学生信息如下:") for student in sorted_students: print(student)
将新功能添加到 operations
字典中:
operations = { "1": handle_add_student, "2": handle_remove_student, "3": handle_update_student, "4": handle_find_student, "5": handle_list_students, "6": handle_exit, "7": handle_sort_students_by_age # 新增功能 }
更新菜单打印函数:
def print_menu(): print("\n学生管理系统") print("1. 添加学生") print("2. 删除学生") print("3. 修改学生信息") print("4. 查询学生信息") print("5. 显示所有学生") print("6. 保存并退出系统") print("7. 按年龄排序显示学生")
通过这种结构化设计,新功能的添加只需定义一个函数,并修改少量代码即可实现。
发布者:LJH,转发请注明出处:https://www.ljh.cool/42159.html