第一题
数据如下:
stu1.txt 孙同学,2020-5-21,20,'男',77,56,77,76,92,58,-91,84,69,-91
stu2.txt 赵同学,2020-11-3,24,'女',65,68,72,95,-81,71,86,91,57,91
stu3.txt 王同学,2021-8-7,25,'男',87,78,90,-76,88,47,100,65,69,100
stu4.txt 李同学,2021-8-10,29,'男',92,54,85,71,-91,68,77,68,95,95
要求如下:
定义Student类,包括name、dob、age、gender和score属性,包括top3方法用来返回学生的最大的3个成绩(可重复)、sanitize方法用来将负的分数变为正的分数,负的分数可能是输入错误。声明stu_list对象组数用于存储所有的学生对象。最后输出所有的学生信息包括姓名、生日、年龄、性别、最高的3个分数。
给出的参考输出结果:
我的代码:
class Student:
def __init__(self, a_name, a_dob, a_age, a_gender, a_score):
self.name = a_name
self.dob = a_dob
self.age = a_age
self.gender = a_gender
self.score = a_score
def top3(self):
return sorted([self.sanitize(s) for s in self.score])[-3:]
def sanitize(self,score_string):
if '-' in score_string:
return int(score_string[1:])
else:
return int(score_string)
def get_score_data(filename):
with open(filename) as f:
line = f.readline()
return line.strip().split(',')
def print_score(student):
print(f"姓名:{student.name},生日:{student.dob},年龄:{student.age},性别:{student.gender},分数:{student.top3()}")
student_list = []
for i in range(1,5):
filename = 'work/stu' + str(i) + '.txt'
stu_record = get_score_data(filename)
stu = Student(stu_record.pop(0), stu_record.pop(0), stu_record.pop(0), stu_record.pop(0), stu_record)
print_score(stu)
student_list.append(stu)
我的输出:
姓名:孙同学,生日:2020-5-21,年龄:20,性别:'男',分数:[91, 91, 92]
姓名:赵同学,生日:2020-11-3,年龄:24,性别:'女',分数:[91, 91, 95]
姓名:王同学,生日:2021-8-7,年龄:25,性别:'男',分数:[90, 100, 100]
姓名:李同学,生日:2021-8-10,年龄:29,性别:'男',分数:[92, 95, 95]
易错点1:top3成绩取的是非重复值的排序,而非包含重复值的排序。分析发现,之所以出现这一差别,原因在于老师在课上给出的代码中使用了set()函数,而set()函数的作用是删除重复值。现在让我们来看一下使用set()函数的代码段:
def top3(self):
return sorted(set([self.sanitize(s) for s in self.score]))[-3:]
此时的输出为:
姓名:孙同学,生日:2020-5-21,年龄:20,性别:'男',分数:[84, 91, 92]
姓名:赵同学,生日:2020-11-3,年龄:24,性别:'女',分数:[86, 91, 95]
姓名:王同学,生日:2021-8-7,年龄:25,性别:'男',分数:[88, 90, 100]
姓名:李同学,生日:2021-8-10,年龄:29,性别:'男',分数:[91, 92, 95]
易错点2:王同学的100去哪儿了?先看错误的输出:
姓名:孙同学,生日:2020-5-21,年龄:20,性别:'男',分数:['91', '91', '92']
姓名:赵同学,生日:2020-11-3,年龄:24,性别:'女',分数:['91', '91', '95']
姓名:王同学,生日:2021-8-7,年龄:25,性别:'男',分数:['87', '88', '90']
姓名:李同学,生日:2021-8-10,年龄:29,性别:'男',分数:['92', '95', '95']
究其原因,是因为此时的分数列表中的分数是字符串格式,而字符串的排序是从逐位排序的,先比较第一个字符,第一个字符相同的情况下再比较第二个字符,以此类推,所以字符串‘100’反而是最小的,所以我们要取top3值是取不到的。所以需要把以下代码段的返回值取整。
def sanitize(self,score_string):
if '-' in score_string:
return score_string[1:]
else:
return score_string
第二题
数据如下:
stu5.txt 特长同学,2020-10-5,20,'男',180,87,98,77,76,92,58,-76,84,69,-47
stu6.txt 特长同学,2020-10-6,20,'女',230,76,48,82,88,92,58,-91,84,69,-68
要求如下:
定义Spostudent、Artstudent为Student的子类,在子类的属性里面新增了spe为特长分数。Spostudent包括的top3方法返回的是最低的3个得分(可重复),Artstudent包括top3方法返回的是最高的3个得分(可重复),最后使用多态的方式输出2个特长同学的姓名、生日、年龄、性别、分数、特长分。
给出的参考输出结果:
我的代码:
class Student:
def __init__(self, a_name, a_dob, a_age, a_gender, a_score):
self.name = a_name
self.dob = a_dob
self.age = a_age
self.gender = a_gender
self.score = a_score
def top3(self):
return sorted(set([self.sanitize(s) for s in self.score]))[0:3]
def sanitize(self,score_string):
if '-' in score_string:
return int(score_string[1:])
else:
return int(score_string)
class Spostudent(Student):
def __init__(self, a_name, a_dob, a_age, a_gender, a_spe, a_score):
Student.__init__(self, a_name, a_dob, a_age, a_gender, a_score)
self.spe = a_spe
class Artstudent(Student):
def __init__(self, a_name, a_dob, a_age, a_gender, a_spe, a_score):
Student.__init__(self, a_name, a_dob, a_age, a_gender, a_score)
self.spe = a_spe
def top3(self):
return sorted([self.sanitize(s) for s in self.score])[-3:]
def get_score_data(filename):
with open(filename) as f:
line = f.readline()
return line.strip().split(',')
def print_score(student):
print(f"姓名:{student.name},生日:{student.dob},年龄:{student.age},性别:{student.gender},分数:{student.top3()},特长分:{student.spe}")
spoStudent = get_score_data('work/stu5.txt')
spoStudent = Spostudent(spoStudent.pop(0), spoStudent.pop(0), spoStudent.pop(0), spoStudent.pop(0), spoStudent.pop(0), spoStudent)
print_score(spoStudent)
artStudent = get_score_data('work/stu6.txt')
artStudent = Artstudent(artStudent.pop(0), artStudent.pop(0), artStudent.pop(0), artStudent.pop(0), artStudent.pop(0), artStudent)
print_score(artStudent)
易错点3:为什么我输出的分数是个空列表?错误的输出如下:
姓名:特长同学,生日:2020-10-5,年龄:20,性别:'男',分数:[],特长分:180
姓名:特长同学,生日:2020-10-6,年龄:20,性别:'女',分数:[],特长分:230
错误的代码段:
class Spostudent(Student):
def __init__(self, a_name, a_dob, a_age, a_gender, a_spe, a_score):
Student.__init__(self, a_name, a_dob, a_age, a_gender, a_score=[])
self.spe = a_spe
class Artstudent(Student):
def __init__(self, a_name, a_dob, a_age, a_gender, a_spe, a_score):
Student.__init__(self, a_name, a_dob, a_age, a_gender, a_score=[])
self.spe = a_spe
原因分析:在定义Spostudent和Artstudent类时,在初始化对象时,'a_score=[]'的作用是将父类student的a_score属性重写为一个空的列表,所以不管传入的参数是什么,最后的输出都会是重写后的空列表。这里很多同学和老师给出的例子搞混了:
class Student:
def __init__(self, a_name, a_dob, a_age, a_gender, a_score=[]):
self.name = a_name
self.dob = a_dob
self.age = a_age
self.gender = a_gender
self.score = a_score
为什么在老师的例子中,'a_score=[]'并没有影响最后的输出呢,这是因为'a_score=[]'在这里定义的是一个默认参数,当没有参数传入时,a_score将默认赋值为一个空列表。两者的含义是不同的。