学校人事管理系统
我们大致上将学校中的人分为三个类别Person,Student和Staff。
Person是基本人员,Student是学生,Staff是教职员工。
他们都具有姓名,性别,出生年月等属性,而学生有成绩、学号等特殊属性,教职员工有工资、入职时间等特殊属性,所以可以将Person作为一个基类,Student和Staff去继承这个基类。
另外,为了防止存入不符要求的信息,我们可以自定义异常类来处理这个问题。
1.项目目录
先创建一个python package,叫做学校人事管理系统的类设计。然后在此package下新建py文件,叫做异常类.py。
后面再创建公共人员类.py,学生类.py和教职工类.py。
2.异常类
class PersonTypeError(TypeError):
pass
class PersonValueError(ValueError):
pass
用来处理输入信息的类型不对或数值异常。
3.公共人员类
import datetime
from Abnormal import PersonTypeError, PersonValueError
class Person:
_num = 0
def __init__(self, name, sex, birthday, ident):
"""
实例对象的基础信息
:param name: 姓名
:param sex: 性别
:param birthday: 出生年月
:param ident: 编号
"""
if not (isinstance(name, str) and sex in ('男', '女')):
# 检查姓名是否是字符串,性别是男还是女
raise PersonValueError(name, sex)
try:
birth = datetime.date(*birthday)
except:
raise PersonValueError('wrong date:', birthday)
self._name = name
self._sex = sex
self._birthday = birth
self._id = ident
# 实例计数
Person._num += 1
def id(self):
return self._id
def name(self):
return self._name
def sex(self):
return self._sex
def birthday(self):
return self._birthday
def age(self):
# 返回年龄
return datetime.date.today().year - self._birthday.year
def set_name(self, name):
"""
修改名字
:param name: 新名字
:return: void
"""
if not isinstance(name, str):
raise PersonValueError('name:', name)
self._name = name
def __lt__(self, other):
"""
根据编号对人物对象排序
:param other: 对象
:return: 对象的id
"""
if not isinstance(other, Person):
raise PersonTypeError(Person)
return self._id < other._id
@classmethod
def num(cls):
# 类方法,用来获得类中人员的计数值
return Person._num
def __str__(self):
# 提供对象的基本信息
return ' '.join((self._id, self._name, self._sex, str(self._birthday)))
def details(self):
# 提供完整信息
return ', '.join(('编号: ' + self._id,
'姓名: ' + self._name,
'年龄: ' + str(self.age()),
'性别: ' + self._sex,
'出生年月: ' + str(self._birthday)))
if __name__ == '__main__':
p1 = Person('小红', '女', (2000, 1, 30), '20181122')
p2 = Person('小明', '男', (2000, 4, 21), '20181130')
p3 = Person('小华', '男', (1999, 12, 23), '20181105')
person_list = [p1, p2, p3]
for person in person_list:
print(person)
print(person.details())
person_list.sort()
print('\n\n--------------------根据编号排序后:')
for person in person_list:
print(person)
print(person.details())
print(f'公共人员类中共有{Person.num()}个人员信息')
代码里对人员的基本信息:姓名,性别,出生年月,年龄等信息做了初始化并记录。下面我们运行一下该程序。
4.学生类
学生是学校里面最主要的人员组成,除了有公共人员的基本属性外,还有选课,成绩,学号等属性。因此,我们需要让Student类在继承Person类的同时,为它新加入一些独有的属性。
import datetime
from Person import Person
from Abnormal import PersonTypeError, PersonValueError
class Student(Person):
_id_num = 0
def __init__(self, name, sex, birthday, department):
"""
学生对象的基础信息
:param name: 学生姓名
:param sex: 学生性别
:param birthday: 学生出生年月
:param department: 学生院系
"""
Person.__init__(self, name, sex, birthday, Student._id_gen())
self._department = department
self._enroll_date = datetime.date.today() # 入学报道日期
self._courses = {}
@classmethod
def _id_gen(cls):
"""
生成学号
:return: 学生学号
"""
cls._id_num += 1
year = datetime.date.today().year
# 学生学号的首位为1,以区分教职工号,入学年份以4位十进制编入学号,序号以5位十进制编入学号
return '1{:04}{:05}'.format(year, cls._id_num)
def department(self):
return self._department
def set_course(self, course_name):
"""
选课
:param course_name: 课程名
:return: void
"""
self._courses[course_name] = None
def set_score(self, course_name, score):
"""
为选定的课打分数
:param course_name: 课程名
:param score: 分数
:return: void
"""
if course_name not in self._courses:
raise PersonValueError('No course was found:', course_name)
self._courses[course_name] = score
def scores(self):
# 得到所有科目的成绩列表
return [(course_name, self._courses[course_name]) for course_name in self._courses]
def details(self):
# 提供完整信息
return ', '.join((Person.details(self),
'入学日期: ' + str(self._enroll_date),
'院系: ' + self._department,
'选课情况: ' + str(self.scores())))
def __lt__(self, other):
"""
根据编号对学生对象倒序排序
:param other: 对象
:return: 对象的id
"""
if not isinstance(other, Student):
raise PersonTypeError(Student)
return self._id > other._id
if __name__ == '__main__':
st1 = Student('小红', '女', (2000, 1, 30), '外语')
st2 = Student('小明', '男', (2000, 4, 21), '物理')
st3 = Student('小华', '男', (1999, 12, 23), '计算机')
st4 = Student('小丽', '女', (2002, 8, 6), '法学')
st1.set_course('英语')
st1.set_score('英语', 85)
st2.set_course('体育')
st2.set_score('体育', 88)
st3.set_course('python')
st3.set_score('python', 95)
st4.set_course('刑法')
st4.set_score('刑法', 93)
student_list = [st1, st2, st3, st4]
for student in student_list:
print(student)
print(student.details())
student_list.sort()
print('\n\n--------------------根据学号排序后:')
for student in student_list:
print(student)
print(student.details())
print(f'学生类中共有{Student.num()}个人员信息')
我们来运行一下程序。可见学生在Person有属性的基础上,又多了几个属性。
5.教职工类
同理,教职工类在继承Person类时,需要加入入职时间,薪资等属性。
import datetime
from Person import Person
from Abnormal import PersonTypeError, PersonValueError
class Staff(Person):
_id_num = 0
def __init__(self, name, sex, birthday, entry_date=None):
"""
教职工对象的基础信息
:param name: 教职工姓名
:param sex: 教职工性别
:param birthday: 教职工出生年月
:param entry_date: 教职工入职日期
"""
super().__init__(name, sex, birthday, Staff._id_gen(birthday))
if entry_date:
# 传入入职日期则记录为传入的日期值
try:
self._entry_date = datetime.date(*entry_date)
except:
raise PersonValueError('wrong date:', entry_date)
else:
# 未传入入职日期,记录为当天入职
self._entry_date = datetime.date.today()
self._salary = 5000 # 教职工月薪
self._department = '未知' # 教职工所在科系
self._position = '未知' # 教职工职位
@classmethod
def _id_gen(cls, birthday):
"""
生成教职工号
:return: 教职工号
"""
cls._id_num += 1
birth_year = datetime.date(*birthday).year
# 教职工号的首位为0,以区分学生工号,出生年份以4位十进制编入教职工号,序号以5位十进制编入教职工号
return '0{:04}{:05}'.format(birth_year, cls._id_num)
def entry_date(self):
return self._entry_date
def set_salary(self, salary):
"""
设置教职工薪水
:param salary: 月薪
:return: void
"""
if not type(salary) is int:
raise TypeError
self._salary = salary
def set_position(self, position):
"""
设置教职工职位
:param position: 职位
:return: void
"""
self._position = position
def set_department(self, department):
"""
设置教职工科系
:param department: 科系名
:return: void
"""
self._department = department
def details(self):
# 提供完整信息
return ', '.join((super().details(),
'入职日期: ' + str(self._entry_date),
'院系: ' + self._department,
'职位: ' + self._position,
'工资: ' + str(self._salary)))
def __lt__(self, other):
"""
根据编号对教职工对象倒序排序
:param other: 对象
:return: 对象的id
"""
if not isinstance(other, Staff):
raise PersonTypeError(Staff)
return self._id > other._id
if __name__ == '__main__':
st1 = Staff('赵刚', '男', (1980, 1, 30), (2013, 10, 1))
st2 = Staff('张强', '男', (1988, 4, 21), (2010, 12, 2))
st3 = Staff('王小红', '女', (1990, 12, 23))
st1.set_salary(8000)
st1.set_department('物理')
st1.set_position('教授')
st2.set_salary(6000)
st2.set_department('计算机')
st3.set_salary(10000)
st3.set_position('副教授')
staff_list = [st1, st2, st3]
for staff in staff_list:
print(staff)
print(staff.details())
staff_list.sort()
print('\n\n--------------------根据教职工号排序后:')
for staff in staff_list:
print(staff)
print(staff.details())
print(f'教职工类中共有{Staff.num()}个人员信息')
这个例子不算很难,但涉及到很多有关Python的类的基础知识,比如Python自定义异常类,类继承,方法重写,类方法的使用,部分魔术方法的使用等,让大家能快速了解一些Python的面向对象用法。
在这个例子的基础上作以修改,再结合Mysql数据库和基于tkiinter或者PyQt的GUI编程,就能打造出一个比较简单的学校人员信息的记录和管理系统了。