「Python」学生管理系统(面向对象)
最近闲着无聊用Python写了个小练习,非常适合初学者,分享下代码。还有一个之前写的基础版的:「Python」学生管理系统(面向对象)
实现思路
一个采用面向对象的学生管理系统,学生作为一个对象Student()
,管理系统也作为一个对象StudentManager()
。包内包含三个文件,分别是:
- main.py,启动文件
- student.py,学生类文件
- managerSystem.py,管理系统类文件
类或对象属性与方法分析
学生对象Student()
主要包含一些属性值:
- stu_id;
- name;
- gender;
- tel;
- address;
- email.
管理对象StudentManager()
主要包含一些方法,可以实现以下功能:
- read_info()、
save_info()
,读取硬盘文件、保存内存中的信息到文件; show_menu()
,展示操作菜单;add_stu()
,添加单条学生信息;edit_stu()
,修改单条学生信息;del_stu()
,删除一条或者多条学生信息;find_stu()
,查询一条或者多条学生信息;make_fake(self, n)
,传入参数n,可以生成n条假的学生信息;make_id_list()
,配合del_stu()
与find_stu()
使用,帮助其实现同时对一条或者多条学生信息进行操作;reorder_stu_id()
,将学生ID重新排序,在每次删除学生信息后调用。
代码实现
main.py:
# -*- coding: utf-8 -*-
"""
@author: ManYacan
@Email: myxc@live.cn
@Website: www.manyacan.com
@time: 2022/04/20 19:18
"""
from managerSystem import * # 导入管理系统模块
if __name__ == '__main__':
# print('main.py已运行~')
stu_manager = StudentManager() # 创建对象
stu_manager.run() # 启动类的入口函数
student.py:
# -*- coding: utf-8 -*-
"""
@author: ManYacan
@Email: myxc@live.cn
@Website: www.manyacan.com
@time: 2022/04/20 19:20
"""
# import prettytable as pt
class Student(object):
"""
定义一个学生类
"""
def __init__(self, stu_id, name, gender, tel, address, email):
"""
学生对象初始化函数
:param name: 姓名
:param gender: 性别
:param tel: 手机号
:param address: 地址
:param email: 邮箱
"""
self.id = stu_id
self.name = name
self.gender = gender
self.tel = tel
self.address = address
self.email = email
def __str__(self):
"""
返回对象说明
:return: 返回学生对象的信息
"""
return f'{self.id}; {self.name}; {self.gender}; {self.tel}; {self.address}; {self.email}'
if __name__ == '__main__':
# 测试类
# student = Student('01', "张三", "男", "13033070911", "河南省宝丰县西大院", "myc@live.com")
# print(student)
managerSystem.py:
# -*- coding: utf-8 -*-
"""
@author: ManYacan
@email: myxc@live.cn
@Website: www.manyacan.com
@time: 2022/04/20 19:21
"""
import random # 配合Faker随机生成性别
import hues # 可以输出带有颜色提示的信息,相当于高级一点的print()
from faker import Faker # 用来制造一些假的学生信息
from student import * # 导入学生类模块
class StudentManager(object):
"""
管理系统类对象
"""
def __init__(self):
"""
对象的初始化
"""
self.stu_list = [] # 存储内存读取的学员数据
self.info_key = ['ID', 'Name', 'Gender', 'Phone', 'Address', 'Email'] # 需要统计或者展示的学生信息列表表头
self.last_stu_id = 0 # 为每个学生定义一个ID号
self.is_edited = False # 记录是否对学生信息进行了修改,如果未作修改,只是查看,那么退出系统的时候不用进行保存提示
def run(self):
"""
类对象入口函数
:return:
"""
self.read_info() # 读取文件信息
hues.info("Welcome to use this student system.") # 欢迎使用系统
while True: # 循环菜单操作
self.show_menu() # 显示菜单
try: # 这里为什么要使用try?因为如果输入字符,这里直接进行int()转换的话会报错
command_num = int(input("Please input the command number:")) # 输入指令
if command_num == 1: # 展示学生列表
self.show_table()
elif command_num == 2: # 添加学生
self.add_stu()
elif command_num == 3: # 修改学生信息
self.edit_stu()
elif command_num == 4: # 删除学生信息
self.del_stu()
elif command_num == 5: # 这里可以同时查看单个学生信息或者多个
self.find_stu(self.make_id_list())
elif command_num == 6: # 保存所有操作
self.save_info()
elif command_num == 7: # 生成虚假学生信息
self.make_fake(int(input("Please input the number that you want to generate:")))
elif command_num == 8: # 对学生ID进行重新排序,清除掉因为删除信息而造成的中间空掉的序号
self.reorder_stu_id()
pass
elif command_num == 9: # 退出系统
if self.is_edited: # 如果对信息进行了修改,退出的时候询问是否保存
save_command = input("Do you want to save the student information?(y)")
if save_command == 'y': # 输入”y“的话就对内存里的信息进行保存
# self.reorder_stu_id()
self.save_info()
else:
hues.warn('The information was edited, but it was not saved!')
else:
hues.info("The information was not edited.")
break
else:
hues.error("Undefined Command number!") # 打印错误信息
except Exception as e:
hues.error("Please enter the command number!")
def read_info(self):
"""
读取系统保存的文件信息
:return:
"""
try:
f = open('student.json', 'r') # 以只读的方式打开文件
except:
hues.log("Not find 'student.json', this system will creat it.")
f = open('student.json', 'w') # 如果读取不到,说明文件不存在,需要创建文件
else:
data = f.read() # 读取文件
if data != '' and data != '[]':
# 如果程序第一次运行,打开了却没在文件中新增信息,那么就会创建一个空的文件,这个时候第二次启动程序因为data='',再进行eval()的话就会报错,所以要排除这种情况。如果读取到了data='',那么直接跳过
read_info_list = eval(data) # 读取到的是字符串,需要转化为列表
self.stu_list = [Student(i['id'], i['name'], i['gender'], i['tel'], i['address'], i['email']) for i in
read_info_list] # 读取到的学生是一个字典,需要将字典转换成对象,然后存放到stu_list()列表中
self.last_stu_id = int(read_info_list[-1]['id']) # 获取最后一个学生的ID
hues.success(f"Read [{len(read_info_list)}] student's information.") # 打印下看看读取到了几条学生信息
else:
hues.info("'student.json' is empty.")
f.close() # 关闭文件
@staticmethod
def show_menu():
"""
以表格的形式打印显示操作菜单
:return:
"""
tb = pt.PrettyTable() # 创建一个美美表格的对象
title_line = "+---------+------+-----+------+--------+------+------+------+---------+------+" # 用来打印输出
print(title_line) # 打印线
print("Student Management System".center(len(title_line), '-'))
tb.field_names = ['Command', 'Show', 'Add', 'Edit', 'Delete', 'Find', 'Save', 'Fake', 'Reorder', 'Quit']
tb.add_row([i for i in range(len(tb.field_names))])
print(tb)
def show_table(self):
"""
以列表的形式展示所有学生信息,并以美美的表格的形式打印出来,得益于stu_list()函数的完善,这个函数的实现很简单
:return:
"""
if len(self.stu_list): # 当学生列表里有元素时
id_list = [i.id for i in self.stu_list] # 创建一个列表用于存放所有的学生姓名,遍历所有的学生姓名
self.find_stu(id_list) # 将学生姓名传递给find_stu()方法
hues.success(f'There are [{len(self.stu_list)}] student information.')
else:
hues.info('There is no student!')
def add_stu(self):
"""
添加学生 name, gender, tel, address, email
:return:
"""
# 用户输入需要进行收集的学生信息
name = input("Please input student's name:")
gender = input("Please input student's gender:")
tel = input("Please input student's tel:")
address = input("Please input student's address:")
email = input("Please input student's email:")
# 使用Student类来添加学生,学生ID需要+1
stu = Student((self.last_stu_id + 1), name, gender, tel, address, email)
self.stu_list.append(stu) # 在学生列表里追加一条学生信息
self.is_edited = True # 对信息进行了修改,打开开关
hues.success(f"Add [{stu.name}]'s information successful!")
def edit_stu(self):
"""
修改学生信息
:return:
"""
edit_name = input("Please input the name that you want to edit:")
for i in self.stu_list:
if edit_name == i.name: # 如果输入的删除名字存在于列表中,那么删除该学生信息
i.name = input("Please enter new name:")
i.gender = input("Please enter new gender:")
i.tel = input("Please enter new tel:")
i.address = input("Please enter new address:")
i.email = input("Please enter new email:")
hues.success(f"[{i.name}]'s information have been updated.")
self.find_stu([i.id])
self.is_edited = True # 对信息进行了修改,打开开关
break
else: # 遍历了学生列表没有查找到学生,说明没有当前学生
hues.error(f"Not find this student: [{edit_name}]!")
def del_stu(self):
"""
删除学生
:return:
"""
id_list = self.make_id_list() # 获取用户输入操作的ID列表
del_success_num = len(id_list) # 记录删除了多少条学生信息,因为ID列表里的ID有可能是不存在的,因此先记录下,当不存在的时候就减去1
hues.warn(f"Start to delete {len(id_list)} student information...")
for stu_id in id_list:
for i in self.stu_list:
if stu_id == i.id: # 如果输入的删除名字存在于列表中,那么删除该学生信息
hues.log(f"Delete [{stu_id}] successful!")
# self.find_stu([i.id])
self.stu_list.remove(i)
self.is_edited = True # 对信息进行了修改,打开开关
break
else: # 遍历了学生列表没有查找到学生,说明没有当前学生
del_success_num = del_success_num - 1 # 当ID不存在的时候就-1
hues.error(f"Not find this student: [{stu_id}]!")
hues.success(f"Delete {del_success_num} student information.") # 打印下一共操作了多少条信息
# self.reorder_stu_id() # 删除的学生信息可能是中间的,例如存在ID:1,2,3,4,如果删除了ID2,3,那么就要将所有学生的ID重排序为1,2
def find_stu(self, ids):
"""
查找学生信息,并以表格的形式打印
:param ids: 这个参数是list形式,里面元素都是int
"""
tb = pt.PrettyTable() # 创建一个美美表格的对象,用来美化显示打印
tb.field_names = self.info_key
for stu_id in ids:
for i in self.stu_list:
if stu_id == i.id: # 如果找到了查找的学生
tb.add_row([i.id, i.name, i.gender, i.tel, i.address, i.email])
break
else: # 遍历了学生列表没有查找到学生,说明没有当前学生
hues.error(f"Not find this student ID:[{stu_id}]!")
print(tb)
def save_info(self):
"""
保存文件
:return:
"""
# stu_list中的学生都是对象,需要循环取出所有对象的属性和属性值,然后转化为字符串写入文件,写入的时候需要注意,需要把字符串中的“'”换成““”,这样在json文件中才能识别;还有就是地址过长时,自动生成的字符串中会包含换行符,需要进行替换掉
f = open("student.json", 'w')
f.write(str([i.__dict__ for i in self.stu_list]).replace('\'', '"'))
self.is_edited = True # 对信息进行了修改,打开开关
hues.success(f'Write {len(self.stu_list)} information...')
def make_fake(self, n):
"""
生成几个虚假学生信息
:return:
"""
fake = Faker()
fake_gender_list = ['W', 'M'] # 随机性别列表
for i in range(n):
self.last_stu_id += 1 # ID不能重复,每次使用前需要+1
# 循环添加虚假的学生信息,fake.address()默认中间会有换行符,需要替换掉
fake_stu = Student(self.last_stu_id, fake.name(), random.choice(fake_gender_list), fake.phone_number(),
fake.address().replace("\n", ' '),
fake.email())
self.stu_list.append(fake_stu)
hues.success(f'Generate [{n}] fake student information.')
self.is_edited = True # 对信息进行了修改,打开开关
hues.warn("If you want to save generated information, you should use command number:6.")
@staticmethod
def make_id_list():
"""
这个方法可以获取用户输入的字符串,然后将其转化成一个学生ID列表
例如:
1、输入”1“,转化成[1]
2、输入”1,2,3“,转化成[1,2,3]
3、输入”1-3“,转化成[1,2,3]
:return: id_list:一个存储学生ID的list
"""
hues.info(
"If you want to find two or more student, please use ',' or '-' to split. For example: '1,2,3', '1-3'")
find_id = input("Please input the id that you want to do:")
if "," in find_id: # 说明输入的是多个名字,需要分隔成列表
id_list = find_id.split(',') # 获取的字符串需要进行分割
for i in range(len(id_list)): # 分割完成后字符串里的元素都是字符串类型的,需要全部进行转换成int,
id_list[i] = int(
id_list[i]) # 因为find_stu()函数内部与self.stu_list中的对象进行对比的时候,student对象的id是int类型的
elif '-' in find_id:
id_start, id_end = find_id.split('-')
id_start, id_end = int(id_start), int(id_end)
id_list = []
for i in range(id_start, id_end + 1):
id_list.append(i)
else: # 说明只输入了一个ID
id_list = [int(find_id)]
return id_list
def reorder_stu_id(self):
"""
对学生的ID进行重新排列:如果按照正常操作的话,学生ID是一个接着一个的,但是如果对中间的进行删除,那么中间缺失的数字就会空出来。
:return:
"""
for i in range(len(self.stu_list)):
self.stu_list[i].id = i + 1
self.is_edited = True # 对信息进行了修改,打开开关
hues.success("Reorder the student's ID.")
# DEBUG
if __name__ == '__main__':
manager_demo = StudentManager() # 创建一个对象
# manager_demo.run() # 启动对象的入口函数