场景编程集锦 - 我要当学霸

时间:2023-02-08 17:08:03

1. 场景描述

场景编程集锦 - 我要当学霸   学霸一词是近年来流行的网络用语,关于学霸的定义网络上也有不同的版本解释,实际上这是一个见仁见智的问题。在我看来,学霸应该具备的三个特点:首先学霸是品学兼优学生;其次是思维灵活、学习力强;最后是考试成绩稳定、名列前茅。学霸是老师的骄傲,学霸绝对是众多同学心目中的yyds,是对标学习的榜样,当然学霸也是某些同学羡慕嫉妒恨的对象。在学校,老师要通过考试来检验教学效果,通过对学生考试成绩和排名分析,了解学生的学习情况,制订学生个性化提升计划,同时也要通过排名分析表扬先进,鞭策后进,实现和达到提升学习成绩的教学目标。 下面我们就使用Python编写一个学生成绩统计分析程序,以帮助老师分析学生的考试成绩,制订教学计划,同时也有利于学生对标学习,追赶学霸。


2. 编程思路

  我们可以使用Python对象编程,实现学生成绩统计分析。定义两个类:一个是学生类Student,另一个为学霸类BestStudents。详细说明如下:

2.1 Student类

属性包括:学生姓名、学生所选科目名称及成绩,可以字典形式存放科目和成绩分数。 方法包括以下内容: get_name():获取学生姓名; get_total():计算学生各科成绩的总分; get_score(subject):获取学生单科分数,subject代表科目; elective(subject):判断学生是否选修某科目,这里的参数subject表示科目名称; print_student():打印学生各科成绩和分数。

2.2 BestStudnets类

学霸类BestStudets包括以下属性: 选择学霸的人数,学生信息列表,其中的学生信息包含姓名、各科成绩分数。 学霸类BestStudents包含以下方法: top_total():找出总成绩前5名的学生,这里把他们称之为学霸。 top_subject(subject):找出单科成绩前5名的学生,参数subject代表学科名称。

2.3 学生成绩存放

我们把学生的成绩保存到文本文件students.txt中,内容如下所示: 场景编程集锦 - 我要当学霸 以上列出了13位同学在某次期末考试中的成绩分数。在这个文本文件中,每一列之间使用制表符‘\t’进行分隔。语文、数学和外语每个科目满分为150分,其他科目满分100分。每个学生考试科目为6个学科,语文、数学和外语为必考科目,其它为选修科目。我们作如下约定:凡是成绩为0分的科目,代表该学生的未选修科目。

2.4 学生成绩加载

此外我们需要从文本文件students.txt读入学生成绩,供后续分析使用。 下面我们就可以进入程序编码阶段。


3. 程序代码

程序代码有两个模块构成。students.py是基础功能模块,主要定义学生类和学霸类;best_students.py是主程序模块。具体代码如下所示:

"""
  students.py : 赶超学霸基础模块
"""
class Student:
    """ 定义学生类 """
    def __init__(self, name, score_lst, column_lst):
        self.name = name
        self.scores = {}
        for idx, score in enumerate(score_lst):
            if score:
                self.scores[column_lst[idx]] = score   # ①

    def get_name(self):
        return self.name

    def get_total(self):
        """ 计算总分 """
        score_list = self.scores.values()   # ②
        total = 0
        for score in score_list:
            total += score
        return total

    def get_score(self, subject):
        """ 获取单科成绩 """
        if self.elective(subject):
            return self.scores[subject]
        else:
            return None

    def elective(self, subject):
        """ 是否选考科目 """
        if subject in self.scores.keys():
            return True
        else:
            return False

def print_student(self):
""" 打印学生成绩 """
        print('姓名\t' + self.name)
        print('总分\t' + str(self.get_total()))
        for subject, score in self.scores.items():   # ③
            print(subject + '\t' + str(score))

class BestStudents:
    """ 找出学霸 """
    def __init__(self, student_lst, numbers=5):
        self.number = numbers
        self.students = student_lst

    def top_total(self):
        """ 总分学霸 """
        
        total_lst = [(stud.get_name(), stud.get_total()) for stud in self.students]   # ④
        
        total_lst.sort(key=lambda stud: stud[1], reverse=True)   # ⑤
        return total_lst[:self.number]

def top_subject(self, subject):
    """ 单科学霸 """
        # 获取选考subject科目学生成绩
        subject_lst = [(stud.get_name(), stud.get_score(subject)) for stud in self.students
                       if stud.elective(subject)]   # ⑥

        # 按成绩进行降序排序
        subject_lst.sort(key=lambda stud: stud[1], reverse=True)
        return subject_lst[:self.number]

重要语句说明如下: 语句①属性scores是一个字典,键是学科名称,值是成绩分数; 语句②取字典scores的成绩分数,生成新的列表; 语句③循环取出字典中的学科名称和成绩分数; 语句④使用列表推导式生成包含学生姓名和总分的元组列表,即列表的每一个元素是元组,这个元组有学生姓名和成绩总分构成。 语句⑤对含有元组元素的列表进行排名,使用学生的成绩总分作为键进行降序排序。 语句⑥获取选考subject科目的学生成绩,生成一个列表,其元素是包括学科名称和成绩分数的元组。

"""
  best_students.py : 赶超学霸
"""
from common.students import *   # ①
STUDENTS_DATA = 'students.txt'

def load_students(file_name):
    """ 从文件中加载学生成绩 """
    student_lst = []
    infile = open(file_name, encoding='utf8', mode='r')
    # 取表头的列名
    while True:
        line = infile.readline().strip()
        # 过滤掉表头前空行
        if line:
            column_lst = line.split('\t')[1:]
            break

    # 获取姓名及各科成绩
    for line in infile:
        if line.strip():
            # 过滤空行
            stud_name, *score_lst = line.strip().split('\t')
            score_lst = [float(score) for score in score_lst]
            student_lst += [Student(stud_name, score_lst, column_lst)]

    infile.close()
    return student_lst

def rank_list(subject, top_stud):
    """ 打印排行榜 """
    title = subject + '排行榜'
    print(title.center(20))
    print('=' * 25)

    for idx, (name, score) in enumerate(top_stud):
        print('第{0}名\t'.format(idx+1) + name.strip() + '\t' + str(score))
    print()

def find_student(stud_lst, name):
    """查询学生信息"""
    status = False
    for stud in stud_lst:
        if stud.get_name() == name.strip():
            stud.print_student()
            status = True
            break
    if not status:
        print('{0}:没有学生信息!'.format(name))

def main():
    stud_list = load_students(STUDENTS_DATA)   # ②
    best_stud = BestStudents(stud_list)   # ③
    rank_list('总分', best_stud.top_total())   # ④
    # 数学排行榜
    rank_list('数学', best_stud.top_subject('数学'))   # ⑤
    rank_list('历史', best_stud.top_subject('历史'))
    rank_list('地理', best_stud.top_subject('地理'))
    rank_list('政治', best_stud.top_subject('政治'))

    print('学生成绩'.center(20))
    print('=' * 25)
    find_student(stud_list, '李博闻')
    print('-' * 25)
    find_student(stud_list, '周立可')

if __name__ == '__main__':
    main()

主要函数说明: 函数load_students():从文本文件中加载学生各学科成绩; 函数rank_list(subject, top_stud):打印排行榜; 函数find_student(stud_lst, name):查询学生的成绩分数。 重要语句说明: 语句①从包common中导入模块students中的所有函数; 语句②从文本文件students.txt中读入学生成绩; 语句③创建BestStudents类的实例best_stud; 语句④生成成绩总分的排行榜,取前五名; 语句⑤生成数学成绩排行榜,取前五名。


4. 运行效果

4.1 程序存放目录

D:\cases\赶超学霸>dir
2022/12/10  15:33             2,141 best_students.py
2022/12/10  16:22    <DIR>          common
2022/12/10  15:58               972 students.txt
D:\cases\赶超学霸>

D:\cases\赶超学霸>cd common
D:\cases\赶超学霸\common>dir
2022/12/10  16:22             2,095 students.py
2022/04/01  07:34               106 __init__.py
D:\cases\赶超学霸\common>

4.2 执行效果

D:\cases\赶超学霸>python best_students.py
       总分排行榜
=========================
第1名   李博闻  741.0
第2名   邱荷    720.0
第3名   李拓    695.0
第4名   柳湘莲  693.0
第5名   周立可  686.0

       数学排行榜
=========================
第1名   李博闻  150.0
第2名   张冲之  149.0
第3名   柳湘莲  145.0
第4名   邱荷    145.0
第5名   姜雪梅  142.0

       历史排行榜
=========================
第1名   万沐春  99.0
第2名   柳湘莲  98.0
第3名   周立可  98.0
第4名   邱荷    96.0
第5名   黄珊    95.0

       地理排行榜
=========================
第1名   白若溪  95.0
第2名   万沐春  95.0
第3名   周立可  88.0
第4名   李拓    87.0
第5名   邱荷    87.0

       政治排行榜
=========================
第1名   李博闻  99.0
第2名   黄珊    85.0
第3名   柳湘莲  83.0
第4名   姜雪梅  83.0
第5名   吕静成  79.0

        学生成绩
=========================
姓名    李博闻
总分    741.0
语文    145.0
数学    150.0
外语    147.0
物理    100.0
政治    99.0
化学    100.0
-------------------------
姓名    周立可
总分    686.0
语文    143.0
数学    140.0
外语    125.0
历史    98.0
地理    88.0
生物    92.0

D:\cases\赶超学霸>

5. 程序优化

  我们可以对当前的程序版本进一步进行优化,主要包括两个方面。一是使用Excel文件格式保存学生成绩分数的原始数据,以代替原来的文本文件格式;二是以统计图表方式展示学霸排行榜,以取代目前的文字显示,使显示的内容更加丰富和直观。