这里做一个学校的人事管理系统中的类的实例化,其中含有的类:Person、Student、Stuff三个类。下面来具体分析类所要实现的功能。
首先可以定义使用Person类,找出学生和教职工之间的共同属性。比如:年龄、姓名、性别、出生日期、入校日期等共有属性。
基本人员的ADT设计,这里要考虑人员的基本信息
ADT Preson #定义人员抽象数据类型
Person(self,strname,strsex,tuple birthday,str ident) #构造人员对象
id(self) #获取人员的编号
name(self) #获取人员姓名
sex(self) #获取人员姓名
birthday(self) #获取人员的出生年月日
age(self) #获取人员的年龄
set_name(self,str name) #修改人员姓名
<(self,Preson another) #基于人员编号比较的两个记录
detials(self) #给出人员记录里保存的数据详情
然后就是学生类的设计了,这里只需要添加成绩、选课、院系、入学日期、学号等独有属性即可。学生ADT的设计,学生属于一个院系,得包含入学时间,成绩等信息,这里可以用Students(Person)继承
ADT Student(Person): #定义学生ADT
Student(self,strsex,tuple birthday,str department) #构造学生对象
department(self) #取得学生所属院系
en_year(self) #取得学生入学日期
scores(self) #取得学生成绩单
set_course(self,str score_name) #学生选课
set_score(self,str course_name,int score) #课程成绩
教职工ADT设计,需要现在考虑教职工的类,应该包含院系、工资、入职时间、工号等独有属性。
ADT Staff(Person): #定义教职工ADT
Staff(self,strname,strsex,tuple birthday,tuple entry_data)#构造教职工对象
department(self) #所属院系
salary(self) #获取教职工工资
entry_data(self) #获取入职时间
position(self) #获取教职工职位
set_salary(self,int amount) #设置教职工工资
......
接下来就是具体的实现了。首先定义两个捕捉错误的类。
# 类定义实例:学校人事管理系统中的类
import datetime
# 派生两个异常类用来捕捉异常
class PersonTypeError(TypeError):
pass
class PersonValueError(ValueError):
pass
然后就是Person类的具体实现了
# 公共人员类的定义
class Person():
_num=0 #统计建立人员对象的个数
def __init__(self,name,sex,birthday,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=birthday
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.data.today().year-self._birthday.year)
def set_name(self,name): #修改名字
if not isinstance(name,str):
raise PersonValueError('set_name:',name)
self.name=name
def __lt__(self,another): #根据两个人的id大小确定记录的大小关系
if not isinstance(another,Person):
raise PersonTypeError(another)
return self._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,
'性别:'+self._sex,
'出生日期:'+str(self._birthday)))
p1=Person('谢雨洁','女',(1995,7,30),'1201510111')
p2=Person('杨玉清','男',(1990,2,10),'1201315613')
p3=Person('徐若夕','女',(2000,9,25),'1206713119')
p4=Person('胡志强','男',(1992,12,10),'1203570301')
plist2=[p1,p2,p3,p4]
for p in plist2:
print(p)
print('\nAfter sorting:')
plist2.sort()
for p in plist2:
print(p.details())
print('people created:',Person.num(),'\n')
父类定义完毕,接着就定义子类Student,子类继承了父类
# 学生类的定义
class Student(Person):
_id_num=0 #统计数量
@classmethod
def _id_gen(cls): # 实现学号的生成规则
cls._id_num+=1
year=datetime.date.today().year
return '1{:04}{:05}'.format(year,cls._id_num)
def __init__(self,name,sex,birthday,department):
Person.__init__(self,name,sex,birthday,Student._id_gen())
self._department=department
self._enroll_data=department.date.today()
self._courses={} # 一个空字典
def set_course(self,course_name):
self._courses[course_name]=None
def set_score(self,course_name,score): # 先选课才有成绩
if course_name not in self._course:
raise PersonValueError('No this course selected:',course_name)
self._courses[course_name]=score
def score(self):
return [(cname,self._course[cname]) for cname in self._course]
def details(self): #覆盖基类
return ' '.join((Person.details(self),
'入学日期:'+str(self._enroll_data),
'院系:'+self._department,
'课程记录:'+str(self.score())))
最后就可以完成子类Staff的定义了。
#教职工类的实现
class Staff(Person):
_id_num=0
@classmethod
def _id_gen(cls,birthday):
cls._id_num+=1
birth_year=datetime.date(*birthday).year
return '0{:04}{:05}'.format(birth_year,cls._id_num)
def __init__(self,name,sex,birthday,entry_data=None):
super().__init__(name,sex,birthday,Staff._id_gen(birthday))
if entry_data:
try:
self._entry_date=datetime.data(*entry_data)
except:
raise PersonValueError('Wrong data:',entry_data)
else:
self._entry_date=datetime.date.today()
self._salary=1800 # 默认设为最低工资,可修改
self._department='None' # 需要设定
self._position='None' # 未定
'''def __lt__(self,another): #根据两个人的id大小确定记录的大小关系,子类不需要再写,可以直接调用父类的
if not isinstance(another,Person):
raise PersonTypeError(another)
return self._id>another._id'''
def set_salary(self,amount):
if not type(amount) is int:
raise TypeError
self._salary=amount
def set_position(self,position):
self._position=position
def set_department(self,department):
self._department=department
def details(self):
# 使用super不需要提供self参数,这里不进行覆盖
return ' '.join((super().details(),
'入职日期:'+str(self._entry_date),
'院系:'+self._department,
'职位:'+self._position,
'工资:'+str(self._salary)))
sta1=Staff('张子瑜','女',(1997,10,16))
sta2=Staff('何蕾蕾','男',(1992,3,19))
print(sta1)
print(sta2)
sta1.set_department('数学系')
sta1.set_position('副教授')
sta1.set_salary(8600)
print(sta1.details())
print(sta2.details())
sta_list=[sta1,sta2]
print('\nAfter sorting:')
sta_list.sort() # 这里调用了父类的__lt__()
for sta in sta_list:
print(sta.details())
print('people created:',Person.num(),'\n') #调用父类
print('people created:',Staff.num(),'\n') #上面方法和下面方法都一样
通过上面代码可加深对python面向对象的了解,也能回顾前面所学的知识——异常。当然,也可以对上述Person接着进行派生。比如学生具体分为本科生以及研究生,教职工分为教师和职工等,通过对上述代码的拓展可以做一个完整的学生管理系统。