0%

用Python写的简易教务系统

需求分析

系统背景介绍

​ 学生信息管理系统是针对学校人事处的大量业务处理工作而开发的管理软件,主要用于学校学生信息管理,总体任务是实现学生信息关系的系统化、科学化、规范化和自动化,其主要任务是用计算机对学生各种信息进行日常管理,如查询、修改、增加、删除,另外还考虑到学生选课,针对这些要求设计了学生信息管理系统。

功能需求分析

  1. 学生成绩管理系统分三种角色:学生、教师和管理员。学生(学号、姓名、性别、班级、出生年月、电话、邮箱、用户名、密码),教师(工号、姓名、联系电话、邮箱、职称、用户名、密码)、管理员(工号、姓名、联系电话、邮箱、用户名、密码);

  2. 管理员可以添加教师和学生,学生和教师进入系统可以更新自己的信息;

  3. 管理员可以对课程管理(添加课程:开课学年、开课学期、课程编号、课程名称、学时、学分、指定任课教师),并指定当前有效的学年、学期;

  4. 学生在有效的学年、学期可进行选课;

  5. 教师对自己所讲授的课录入学生成绩,查看成绩(查看成绩显示:学号、姓名、性别、班级、成绩),实现该门课程成绩段的柱状和饼状分布图;

  6. 管理员和学生可以查看成绩,学生可以查看自己的所有成绩(查看成绩显示:课程名称、开课学期、开课学年、学时、学分、成绩、任课教师),管理员可以查看某门课程的所有学生成绩(学号、姓名、性别、班级、成绩)和查看某名学生的所有成绩(查看某名学生成绩显示:课程名称、开课学期、开课学年、学时、学分、成绩、任课教师);

  7. 数据存储在txt文本当中,要求用面向对象编程思想实现;

    总体设计

    系统功能结构

    1

    系统流程图

    2

    开发及运行环境

    Windows 10 1903、JetBrains PyCharm 2019.1.2 x64、Python3.7

    详细设计

    ​ 首先我想的是,通过五个文本分别存储:管理员信息、教师信息、学生信息、课程、成绩,进行储存。

    三个类的父类(Person类):因为我发现了三个对象,老师、学生、管理员,有学号/工号、名字、电话、邮箱、用户名、密码,6个属性的信息是重合的,并且每个对象都可以更新自己的信息,所以在此类我建立了这六个属性,并且添加了更新信息的函数updata(因为担心内置函数update的混用,故用updata data也是数据的意思)。

​ 管理员信息:继承Person类添加了:添加管理员函数addAdmin,添加教师函数addTeacher,添加学生函数addStudent,添加课程函数addElective,设置当前学期学年函数setYearAndSchoolTerm,查看某门科目成绩的函数seeSubjectGrade,查看某名学生所以成绩的函数seeStudentGrade。并将初始化的对象全部存入一个列表里ListAdmin。

​ 教师信息:继承Person类添加了:从管理员决定了建立课程后查找自己上什么课的函数findSubject,为这门课录入成绩的函数setGrade,查看这门成绩的函数seeGrade。并将初始化的对象全部存入一个列表里ListTeacher。

​ 学生信息:继承Person类添加了:选课的函数chooseElective,添加了查看自己成绩的函数seeGrade。并将初始化的对象全部存入一个列表里ListStudent。

​ 课程:用一个字典来保存,每一个课程的课程编号就是key,而其他的元素(开课学年、开课学期、课程名称、学时、学分、任课老师(工号))便是key对应的value值。

​ 成绩:也用字典来保存,每一个学生的学号便是key值,对应的value值也用字典来保存,分别对应了该学生某科目和某科目的成绩

​ 关于保存:保存的方法就是一种,将列表或字典通过以下代码进行保存:

f = open(‘Test.txt’, ‘r’)

a = f.read()

ListOrDict = eval(a)

f.close()

成绩和课程本身就是字典可以直接保存,但是其他三个对象,首先读取用列表装上,而列表的每一个元素也是列表,用来装一个对象的所有属性。

​ 关于读取:通过读取列表中的所有元素,对于成绩和课程本身就是字典就不需要进行其他加工,而三个对象,便提前列表中的的元素进行重新建立对象。

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
#
# Created by 方子希 on 2019/6/1.
#

import matplotlib
import matplotlib.pyplot as plt

YEAR = "2019" # 当前学年初始化
SCHOOLTERM = "3" # 当前学期初始化


class Person:
# 人类(以下所有类的父类)
def __init__(self, ID, name, tel, mail, userName, userPassword):
self.ID = ID
self.name = name
self.tel = tel
self.mail = mail
self.userName = userName
self.userPassword = userPassword

def updata(self):
# 更新信息
temp = int(input("请输入您需要更新什么信息:"
"1、学号/工号(为保证系统正常已经屏蔽)。2、姓名。3、电话。4、邮箱。5、用户名。6、密码。7、退出。\n"))
if (temp == 1):
print("已经屏蔽若需使用请在代码上解开注释!")
# self.ID = input("请输入你想更新的学号/工号:")
# print("更新后的学号/工号为:" + self.ID)
elif (temp == 2):
self.name = input("请输入你想更新的姓名:")
print("更新后的姓名为:" + self.name)
elif (temp == 3):
self.tel = input("请输入你想更新的电话:")
print("更新后的电话为:" + self.tel)
elif (temp == 4):
self.mail = input("请输入你想更新的邮箱:")
print("更新后的邮箱为:" + self.mail)
elif temp == 5:
self.userName = input("请输入你想更新的用户名:")
print("更新后的用户名为:" + self.userName)
elif temp == 6:
self.userPassword = input("请输入你想更新的密码:")
print("更新后的密码为:" + self.userPassword)
elif temp == 7:
return
else:
print("输入有误!")


class Student(Person):
# 学生进入系统可以更新自己的信息
def __init__(self, ID, name, sex, cclass, born, tel, mail, userName, userPassword):
# 学生(学号、姓名、性别、班级、出生年月、电话、邮箱、用户名、密码)
super().__init__(ID, name, tel, mail, userName, userPassword)
self.sex = sex
self.cclass = cclass
self.born = born

def chooseElective(self):
# 选课
for E in ListElective:
if ListElective[E][0] == YEAR and ListElective[E][1] == SCHOOLTERM:
print(
"你可选的课有:\n" + "学年:" + ListElective[E][0] + " 学期:" + ListElective[E][1] + " 课程名:" + ListElective[E][
2] + " 学时:" + ListElective[E][3])
print("是否选择此课?")
temp = int(input("1、确认选择此课。2、不选择此课。\n"))
if temp == 1:
ListScore[self.ID].update({E: "还未出成绩!"})
elif temp == 2:
continue
else:
print("输入有误!")
else:
continue

def seeGrade(self):
# 查看成绩
for S in ListScore[self.ID]:
print("科目:" + S + " 的成绩是:" + ListScore[self.ID][S])


class Teacher(Person):
# 教师进入系统可以更新自己的信息
def __init__(self, ID, name, tel, mail, userName, userPassword, subject=""):
# 教师(工号、姓名、联系电话、邮箱、职称、用户名、密码)
super().__init__(ID, name, tel, mail, userName, userPassword)
self.data = []
self.size = [0, 0, 0, 0]

def findSubject(self):
# 查看自己上的课是什么
for E in ListElective:
if ListElective[E][5] == self.ID:
self.subject = E
print("您上的课是:" + ListElective[E][3] + " 课序号是:" + E)
return
print("未找到您上什么课!")

def setGrade(self):
# 录入本课成绩
self.findSubject()
for S in ListScore:
for E in ListScore[S]:
if E == self.subject:
score = input("学号为 " + S + " 学生的成绩是:")
ListScore[S].update({E: score})
print("所有学生遍历完毕!")

def seeGrade(self):
# 查看本课成绩
self.findSubject()
for S in ListScore:
for E in ListScore[S]:
if E == self.subject:
print("学号为 " + S + " 学生的成绩是:" + ListScore[S][E])
print("所有学生遍历完毕!")

def show11(self):#柱状图的数据准备
self.findSubject()
for S in ListScore:
for E in ListScore[S]:
if E == self.subject:
self.data.append(ListScore[S][E])
self.show1(self.data)

def show1(self, data):#柱状图的显示
# 设置matplotlib正常显示中文和负号
matplotlib.rcParams['font.sans-serif'] = ['SimHei'] # 用黑体显示中文
matplotlib.rcParams['axes.unicode_minus'] = False # 正常显示负号

plt.hist(data, bins=40, facecolor="blue", edgecolor="black", alpha=0.7)
# 显示横轴标签
plt.xlabel("成绩")
# 显示纵轴标签
plt.ylabel("频数")
# 显示图标题
plt.title("频数成绩直方图")

plt.show()

def show22(self):#饼状图的数据准备
self.findSubject()
for S in ListScore:
for E in ListScore[S]:
if E == self.subject:
self.data.append(ListScore[S][E])

a = 0
b = 0
c = 0
d = 0
for f in self.data:
if f <= "25":
a = a + 1
elif "26" <= f <= "50":
b = b + 1
elif "51" <= f <= "75":
c = c + 1
elif "76" <= f:
d = d + 1
else:
print("Wrong!")
return
size = [a, b, c, d]
self.show2(size)

def show2(self, size):#饼状图的显示
import matplotlib.pyplot as plt
import matplotlib

matplotlib.rcParams['font.sans-serif'] = ['SimHei']
matplotlib.rcParams['axes.unicode_minus'] = False

label_list = ['0~25', '26~50', '51~75', '76~100'] # 各部分标签
# size = [1,1,1,1] # 各部分大小学生成绩管理系统.py
color = ["red", "green", "blue", "yellow"] # 各部分颜色
explode = [0.05, 0.05, 0.05, 0.05] # 各部分突出值

plt.pie(size, explode=explode, colors=color, labels=label_list, labeldistance=1.1,
autopct="%1.1f%%", shadow=False, startangle=90, pctdistance=0.6)
plt.axis("equal") # 设置横轴和纵轴大小相等,这样饼才是圆的
plt.legend()
plt.show()


class Admin(Person):
# 管理员(工号、姓名、联系电话、邮箱、用户名、密码)
def __init__(self, ID, name, tel, mail, userName, userPassword):
super().__init__(ID, name, tel, mail, userName, userPassword)

# @staticmethod 本来想 第一个得设立管理员 就用静态函数用类调用 后面直接往txt写信息就好了
def addAdmin(self):
# 添加管理员
adminID = input("输入创建的管理员的ID:")
adminName = input("请输入姓名:")
adminTel = input("请输入电话:")
adminMail = input("请输入邮箱:")
adminUserName = input("请输入用户名:")
adminUserPassword = input("请输入密码:")
admin = Admin(adminID, adminName, adminTel, adminMail, adminUserName, adminUserPassword)
ListAdmin.append(admin)

def addTeacher(self):
# 添加教师
teacherID = input("输入创建的老师的ID:")
teacherName = input("请输入姓名:")
teacherTel = input("请输入电话:")
teacherMail = input("请输入邮箱:")
teacherUserName = input("请输入用户名:")
teacherUserPassword = input("请输入密码:")
teacher = Teacher(teacherID, teacherName, teacherTel, teacherMail, teacherUserName, teacherUserPassword);
ListTeacher.append(teacher)

def addStudent(self):
# 添加学生
studentID = input("请输入创建的学生的ID:")
studentName = input("请输入姓名:")
studentSex = input("请输入性别:")
studentClass = input("请输入班级:")
studentBorn = input("请输入生日:")
studentTel = input("请输入电话:")
studentMail = input("请输入邮箱:")
studentUserName = input("请输入用户名:")
studentUserPassword = input("请输入密码:")
student = Student(studentID, studentName, studentSex, studentClass, studentBorn, studentTel, studentMail,
studentUserName, studentUserPassword)
ListStudent.append(student)
ListScore.update({studentID: {}})

def addElective(self):
# 添加课程
electiveYear = input("请输入开课学年:")
electiveSchoolTerm = input("请输入开课学期:")
electiveID = input("请输入课程编号:")
electiveName = input("请输入课程名称:")
electiveStuTime = input("请输入学时:")
electiveStuGrade = input("请输入学分:")
electiveTeacher = input("请输入指定任课老师:")
ListElective.update({electiveID: [electiveYear, electiveSchoolTerm, electiveName, electiveStuTime,
electiveStuGrade, electiveTeacher]})

def setYearAndSchoolTerm(self):
# 设置当前学年学期
global YEAR
YEAR = input("学年:")
print("更改后当前的学年为:" + YEAR)
global SCHOOLTERM
SCHOOLTERM = input("学期:")
print("更改后当前的学期为:" + SCHOOLTERM)

def seeSubjectGrade(self):
# 查看某科目的所有成绩
temp = input("请输入您想看的科目序号:")
for S in ListScore:
for E in ListScore[S]:
if E == temp:
print("学号为:" + S + "的学生,这个学生的成绩是:" + ListScore[S][E])

def seeStudentGrade(self):
# 查看某学生的所有成绩
temp = input("请输入您想看的学生学号:")
for S in ListScore:
if S == temp:
for E in ListScore[S]:
print(S + "学生的" + E + "科目的成绩是:" + ListScore[S][E])


# 存放学生对象的列表
ListStudent = []

# 存放老师对象的列表
ListTeacher = []

# 存放管理员对象的列表
ListAdmin = []

# 存学生信息
liststudent = []
# 读取学生信息并建立对象写入对象列表
f = open('StudentData.txt', 'r')
a = f.read()
liststudent = eval(a)
f.close()
for l in range(len(liststudent)):
a = Student(liststudent[l][0], liststudent[l][1], liststudent[l][2], liststudent[l][3], liststudent[l][4],
liststudent[l][5], liststudent[l][6], liststudent[l][7], liststudent[l][8])
ListStudent.append(a)
liststudent = [] # 初始化为空防止保存的时候重复

# 存老师信息
listteacher = []
# 读取老师信息并建立对象写入对象列表
f = open('TeacherData.txt', 'r')
a = f.read()
listteacher = eval(a)
f.close()
for l in range(len(listteacher)):
a = Teacher(listteacher[l][0], listteacher[l][1], listteacher[l][2], listteacher[l][3], listteacher[l][4],
listteacher[l][5])
ListTeacher.append(a)
listteacher = [] # 初始化为空防止保存的时候重复

# 存管理员信息
listadmin = []
# 读取管理员并建立对象写入对象列表
f = open('AdminData.txt', 'r')
a = f.read()
listadmin = eval(a)
f.close()
for l in range(len(listadmin)):
a = Admin(listadmin[l][0], listadmin[l][1], listadmin[l][2], listadmin[l][3], listadmin[l][4], listadmin[l][5])
ListAdmin.append(a)
listadmin = [] # 初始化为空防止保存的时候重复

# 存放课程
ListElective = {}
# 读取课程
f = open('ElectiveData.txt', 'r')
a = f.read()
ListElective = eval(a)
f.close()

# 存放成绩
ListScore = {}
# 读取成绩
f = open('ScoreData.txt', 'r')
a = f.read()
ListScore = eval(a)
f.close()


def LogOn(Person):
# 登录校验函数
userName = input("请输入您的用户名:")
userPassword = input("请输入您的密码:")
for P in Person:
if userName == P.userName:
if userPassword == P.userPassword:
print("恭喜你成功登录!")
return P # 正确
else:
print("密码有误!")
return 0 # 密码有误
print("无此用户!")
return 0 # 无此用户


def AdminMenu(Person):
# 管理员的菜单
while (1):
temp = int(input("1、添加(学生/教师/课程/管理员)功能。2、查询(成绩)功能。3、设置(学年)功能。4、更新信息。5、退出\n"))
if temp == 1:
ttemp = int(input("1、添加教师。2、添加学生。3、添加课程。4、添加管理员。5、退出。\n"))
if ttemp == 1:
Person.addTeacher()
elif ttemp == 2:
Person.addStudent()
elif ttemp == 3:
Person.addElective()
elif ttemp == 4:
Person.addAdmin()
elif ttemp == 5:
break
else:
print("输入有误!")
elif temp == 2:
tttemp = int(input("1、查询单个科目成绩。2、查询单个学生成绩。\n"))
if tttemp == 1:
Person.seeSubjectGrade()
elif tttemp == 2:
Person.seeStudentGrade()
else:
print("输入有误!")
elif temp == 3:
ttttemp = int(input("1、设置学期。2、设置学年。\n"))
if ttttemp == 1:
global SCHOOLTERM
SCHOOLTERM = input("请输入您想设置的学期:")
print("更改后当前的学期为:" + SCHOOLTERM)
elif ttttemp == 2:
global YEAR
YEAR = input("请输入您想设置的学年:")
print("更改后当前的学年为:" + YEAR)
else:
print("输入有误!")
elif temp == 4:
Person.updata()
elif temp == 5:
break
else:
print("输入有误!")
return


def TeacherMenu(Teacher):
# 教师的菜单
while (1):
temp = int(input("1、录入成绩。2、查询成绩。3、更新信息。4、查看饼状图。5、查看柱状图。6、退出。\n"))
if temp == 1:
Teacher.setGrade()
elif temp == 2:
Teacher.seeGrade()
elif temp == 3:
Teacher.updata()
elif temp == 4:
Teacher.show22()
elif temp == 5:
Teacher.show11()
elif temp == 6:
break
else:
print("输入有误!")
return


def StudentMenu(Person):
# 学生的菜单
while (1):
temp = int(input("1、选课。2、查询成绩。3、更新信息。4、退出\n"))
if temp == 1:
Person.chooseElective()
elif temp == 2:
Person.seeGrade()
elif temp == 3:
Person.updata()
elif temp == 4:
break
else:
print("输入有误!")
return


# 调试信息 已经直接录入txt 所以舍弃 也可以取消注释使用
# a = Admin("001", "Admin", "15877032128", "1075267114@qq.com", "admin", "admin")
# ListAdmin.append(a)

# t = Teacher("001", "王红斌!", "13833888833", "13833888833@tel.com", "teacher", "teacher")
# ListTeacher.append(t)
#
# t = Teacher("002", "王红", "13833888833", "13833888833@tel.com", "teacher", "teacher")
# ListTeacher.append(t)

# s = Student("001", "LJJ", "Girl", "173", "0826", "13833888833", "13833888833@tel.com", "student", "student")
# ListStudent.append(s)


while (1):
# 主菜单
temp = int(input("请问您是:1、管理员。2、教师。3、学生。4、退出。\n"))
if temp == 1:
a = LogOn(ListAdmin)
if a == 0:
continue
else:
AdminMenu(a)
elif temp == 2:
a = LogOn(ListTeacher)
if a == 0:
continue
else:
TeacherMenu(a)
elif temp == 3:
a = LogOn(ListStudent)
if a == 0:
continue
else:
StudentMenu(a)
elif temp == 4:
break
else:
print("输入有误!")

# 将学生信息保存
for A in ListStudent:
liststudent.append([A.ID, A.name, A.sex, A.cclass, A.born, A.tel, A.mail, A.userName, A.userPassword])
f = open('StudentData.txt', 'w')
f.write(str(liststudent))
f.close()

# 将老师信息保存
for A in ListTeacher:
listteacher.append([A.ID, A.name, A.tel, A.mail, A.userName, A.userPassword])
f = open('TeacherData.txt', 'w')
f.write(str(listteacher))
f.close()

# 将管理员信息保存
for A in ListAdmin:
listadmin.append([A.ID, A.name, A.tel, A.mail, A.userName, A.userPassword])
f = open('AdminData.txt', 'w')
f.write(str(listadmin))
f.close()

# 将成绩保存
f = open('ScoreData.txt', 'w')
f.write(str(ListScore))
f.close()

# 将课程保存
f = open('ElectiveData.txt', 'w')
f.write(str(ListElective))
f.close()

程序运行的部分截图

3

4

5

6

7

8

总结

首先,很幸运,我们专业的这一届是第一届开始学python的,我认为这门课程所用的语言非常的奇妙,老师也兢兢业业,让我们更好的了解Python这门课程真正的用途,而完成这份报告让我收获了很多。

其次,刚刚开始拿到这份报告的时候,看了功能,特别特别多,内心无比恐慌,也非常的不知道从何下手,看见了一句要求“用面向对象编程思想实现”我就开始一步一步设计这个程序,面对三个不同的对象,却又有相同点,使用了类的继承,而三个对象又拥有不同的权限,便在他们之下添加专门的函数。

接下来,就是一步一步的实现,调试,优化,独立完成此报告,或许花的时间是别人的很多很多,但是收获是巨大的,可以熟练使用python的基本操作,并且巩固了基础,就比如我定义的常量YEAR和SCHOOLTERM,在函数中改变的时候,一出函数又回到原来值,深究其原因,发现自己忽略了python课程很早很早就讲了的引用,在函数内不使用global修饰,就会再另开一个空间叫YEAR或SCHOOLTERM,然后进行赋值(指向数据所存位置),但是与外部的全局变量是完全不同的两个值。

最后,写完了这份报告,让我发现了,有些事情刚刚开始看起来很庞大,但是当昨完的那一刻发现也不过如此,愿其他任何事情,也不能有服输的心态。