偷学Python之最后的项目一:学生管理系统(进阶版)
古之立大事者,不惟有超世之才,亦必有坚忍不拔之志。——苏轼
假装有个标题
经过一个多月的学习,终于把Python的基础部分给拿下了,现在自己对Python的也有了一些基础的了解了。
那现在就要开始搞一些项目来扩充自己的编程思维,今天把第十四天的学生管理系统给升级一下,之前是依靠字典和列表完成的而且不能永久存储,程序关闭以后之前的存储的学生信息也会不见,今天用正则表达式和file类的函数来完成改写,完成永久存储任意随时访问的一个小项目。
废话不多说开始进入真题
第一步:还是设计一个大体的结构,分别是菜单、添加学生信息、删除学生信息、修改学生信息、查询学生信息、查询全部信息、程序入口;分别定义一个函数体
"""
-*- coding:uft-8 -*-
author: 小甜
"""
import re # 需要用到正则表达式,提前导入re库
def menu(): # 菜单
pass
def add_stu(stu_file): # 添加学生信息
pass
def del_stu(stu_file): # 删除学生信息
pass
def change_stu(stu_file): # 修改学生信息
pass
def query_stu(stu_file): # 查询学生信息
pass
def query_all_stu(stu_file): # 查询全部信息
pass
def main(stu_file): # 程序入口
pass
if __name__ == '__main__':
students_file = "test.txt" # 用来存储学生信息的.txt文件
main(students_file) # 调用程序开始函数
第二步:定义一个菜单
# 菜单
def menu():
print("-" * 30)
print(''' 学生管理系统
1.添加学生信息
2.删除学生信息
3.修改学生信息
4.查询学生信息
5.查询所有学生信息
6.退出系统''')
到这都是上次的内容,没有什么好说的
第三步:完成添加学生信息的函数;通过input
从键盘键入学生的各种信息,skip
这个变量来记录学号是否存在、with...as
来打开文件,这个的一个好处就是不会出现文件没有关闭的情况,脱离这个语句块文件就已经关闭了
# 添加学生信息
def add_stu(stu_file):
print("您选择了添加学生信息功能")
stu_id = input("请输入您要添加学生的学号:")
stu_name = input("请输入您要添加学生的姓名:")
stu_sex = input("请输入您要添加学生的性别:")
skip = False # 用来记录是否有重复的学号
with open(stu_file, mode="a+", encoding="utf8") as file:
file.seek(0, 0) # 将文件中的光标定位到最开始
line = file.read() # 得到文本内容
pattern = r'\n+' # 将取出的内容以换行符做分隔
content = re.split(pattern, line) # 不限制次数分隔
for stu in content:
reg_id = r'(?<=学号:)\d+' # 匹配学号的的正则表达式
try:
pure_stu_id = re.search(reg_id, stu).group() # 取内容的时候取到的最后一个是空行,所以search的最后一个值为none,没有group属性
if pure_stu_id == stu_id:
skip = True
except AttributeError: # 出现异常直接越过
pass
if skip:
print("该学号已经添加")
else:
new_stu_id = stu_id.ljust(20) # 将其设置为宽度20,不够空格填充,左对齐
new_stu_name = stu_name.ljust(15)
new_stu_sex = stu_sex.ljust(15)
file.write("学号:" + new_stu_id) # 将字符串拼接写入
file.write("姓名:" + new_stu_name)
file.write("性别:" + new_stu_sex)
file.write("\n") # 添加完毕给一个换行
return
这里用到的知识点
- Python中对文件的操作:打开(打开模式、编码规则)、写入、光标定位、读取内容。具体实例参照第二十五的对文件的操作
- 错误与异常:具体实例参照第三十天:Python中的错误和异常
- Python中正则表达式和re模块的运行:零宽断言、
re.search
函数。具体应用实例参照第三十一天的正则语法以及re模块的使用- 还有一个小的知识点就是字符串的格式化,
str.ljust
函数,具体应用参照第八天的字符串的应用
第四步:定义删除学习信息的函数,这里是通过将需要删除的学生信息剔除出来,然后将其重新写入到.txt
文件
# 定义删除学习信息的函数
# 将其全部取出来剔除之后再写入
def del_stu(stu_file):
print("您选择了删除学生信息功能")
del_stu_id = input("请输入您要删除的学号:")
skip = True
with open(stu_file, mode="a+", encoding="utf8") as file:
file.seek(0, 0)
line = file.read()
pattern = r'\n+'
content = re.split(pattern, line)
new_content = "" # 用来存储信息
for stu in content:
reg_id = r'(?<=学号:)\d+'
try:
pure_stu_id = re.search(reg_id, stu).group()
if pure_stu_id == del_stu_id:
skip = False
else:
new_stu = stu + "\n" # 还是换行问题
new_content += new_stu # 如果不是要删除的学号,将信息存取到一个临时变量中
# print(new_content) # 测试用
except AttributeError:
pass
if skip:
print("该学生不在系统中")
else:
file.seek(0, 0) # 将指针置为0
file.truncate() # 删除内容
file.write(new_content) # 重新写入
print("删除成功")
return
这里用到的知识点:
file.truncate()
函数是将文本中的内容全部剔除,参照第二十五的对文件的操作
第五步:完成修改学生信息的函数体,
# 修改信息功能
# 通过正则中的替换功能,将其替换后追加到末尾
def change_stu(stu_file):
def change_menu(): # 定义一个子菜单
print("""--选择你要修改的信息--
1. 修改学号
2. 修改姓名
3. 修改性别
4. 退出修改""")
def change_id():
print("您选择了修改学号信息功能")
change_stu_id = input("请输入您要修改的学号:")
new_stu_id = input("请输入修改后的学号:")
skip = True
with open(stu_file, mode="a+", encoding="utf8") as file:
file.seek(0, 0)
line = file.read()
pattern = r'\n+'
content = re.split(pattern, line)
new_content = ""
for stu in content:
reg_id = r'(?<=学号:)\d+'
try:
pure_stu_id = re.search(reg_id, stu).group()
if pure_stu_id == change_stu_id:
skip = False
stu_aft = re.sub(reg_id, new_stu_id, stu)
else:
new_stu = stu + "\n" # 还是换行问题
new_content += new_stu # 如果不是要删除的学号,将信息存取到一个临时变量中
except AttributeError:
pass
if skip:
print("系统中没有该学生的信息")
else:
file.seek(0, 0) # 将指针置为0
file.truncate() # 删除内容
file.write(new_content)
file.write(stu_aft + "\n")
print("信息修改完毕")
def change_name():
print("您选择了修改姓名信息功能")
change_stu_id = input("请输入您要修改姓名的学号:")
new_stu_name = input("请输入修改后的姓名:")
skip = True
with open(stu_file, mode="a+", encoding="utf8") as file:
file.seek(0, 0)
line = file.read()
pattern = r'\n+'
content = re.split(pattern, line)
new_content = ""
for stu in content:
reg_id = r'(?<=学号:)\d+'
reg_name = r'(?<=姓名:)\w+'
try:
pure_stu_id = re.search(reg_id, stu).group()
if pure_stu_id == change_stu_id:
skip = False
stu_aft = re.sub(reg_name, new_stu_name, stu)
else:
new_stu = stu + "\n" # 还是换行问题
new_content += new_stu # 如果不是要删除的学号,将信息存取到一个临时变量中
except AttributeError:
pass
if skip:
print("系统中没有该学生的信息")
else:
file.seek(0, 0) # 将指针置为0
file.truncate() # 删除内容
file.write(new_content)
file.write(stu_aft + "\n")
print("信息修改完毕")
def change_sex():
print("您选择了修改性别信息功能")
change_stu_id = input("请输入您要修改性别的学号:")
new_stu_sex = input("请输入修改后的性别:")
skip = True
with open(stu_file, mode="a+", encoding="utf8") as file:
file.seek(0, 0)
line = file.read()
pattern = r'\n+'
content = re.split(pattern, line)
new_content = ""
for stu in content:
reg_id = r'(?<=学号:)\d+'
reg_sex = r'(?<=性别:)\w+'
try:
pure_stu_id = re.search(reg_id, stu).group()
if pure_stu_id == change_stu_id:
skip = False
stu_aft = re.sub(reg_sex, new_stu_sex, stu)
else:
new_stu = stu + "\n" # 还是换行问题
new_content += new_stu # 如果不是要删除的学号,将信息存取到一个临时变量中
except AttributeError:
pass
if skip:
print("系统中没有该学生的信息")
else:
file.seek(0, 0) # 将指针置为0
file.truncate() # 删除内容
file.write(new_content)
file.write(stu_aft + "\n")
print("信息修改完毕")
while True:
change_menu() # 调用子菜单
alter_num = int(input("请输入功能序号:"))
if alter_num == 1:
change_id()
elif alter_num == 2:
change_name()
elif alter_num == 3:
change_sex()
elif alter_num == 4:
break
else:
print("输入有误")
不足:此段代码的冗余非常之强大,目前的自己肚子里的知识有限,难以使其优雅的发挥Python的特性
用到的知识点:
re模块中的
re.sub
函数,具体实例参照第三十一天的正则语法以及re模块的使用
最后一步:完成剩下的函数体
# 查看某个学生功能
def query_stu(stu_file):
print("您选择了查询学生信息功能")
query_stu_id = input("请输入您要查询的学号:")
skip = True
with open(stu_file, encoding="utf8") as file:
file.seek(0, 0)
line = file.read()
pattern = r'\n+'
content = re.split(pattern, line)
for stu in content:
reg_id = r'(?<=学号:)\d+'
try:
pure_stu_id = re.search(reg_id, stu).group()
if pure_stu_id == query_stu_id:
skip = False
stu_info = stu
except AttributeError:
pass
if skip:
print("该学生不在系统中")
else:
print('找到此学生,信息如下↓↓↓↓↓↓↓↓')
print(stu_info)
# 查询全部信息
def query_all_stu(stu_file):
with open(stu_file, encoding="utf8")as file:
line = file.read()
pattern = r'\n+'
content = re.split(pattern, line)
print("全部学生信息如下")
for stu in content:
print(stu)
# 程序入口
def main(stu_file): # 程序入口
while True:
menu()
number = input("请输入想要的功能:")
if number == str(1):
add_stu(stu_file)
elif number == str(2):
del_stu(stu_file)
elif number == str(3):
change_stu(stu_file)
elif number == str(4):
query_stu(stu_file)
elif number == str(5):
query_all_stu(stu_file)
elif number == str(6):
whether_to_quit = input("是否退出(y/n)")
while True:
if whether_to_quit == 'y' or whether_to_quit == 'Y' or whether_to_quit == 'yes':
print("已退出")
exit()
elif whether_to_quit == 'n' or whether_to_quit == 'N' or whether_to_quit == 'no':
print("取消取出")
break
else:
print("输入错误,退出失败")
break
else:
print("输入错误,请重新输入")
if __name__ == '__main__':
students_file = "test.txt"
main(students_file)
最后就没有什么难点了,基本就是套用上次的代码
这次就不附上完整的代码了,毕竟接近300行的东西一下copy过来有点不合适,前面的代码逐步复制就可以直接运行
效果图
-
添加数据并退出(添加王美丽和周富贵)
-
删除数据(将周富贵删除)
-
修改数据(将王美丽修改为周富贵)
-
查看数据(在这之前随便添加几组数据)
总结
对之前的学生管理系统做了一个进阶