组合类替换嵌套内置类型实现多层嵌套业务
admin
2024-02-13 08:24:11

组合类替换嵌套内置类型实现多层嵌套业务

1.概述

如果在开发的业务中遇到嵌套数据,通常我们会使用字典、元组、集合、列表等内置的类型嵌套组合存储数据,例如保存每个学生课程的成绩,它的属性包含姓名,课程,分数。通过内置的字典和列表嵌套实现了存储学生、课程、分数{‘name’:{‘subject’:[score]}}
这种通过嵌套内置类型存储数据的方式在开发中也是经常使用,但是随着业务逻辑的复杂,内置类型的嵌套的层级就越复杂,操作这个嵌套的对象就会非常的复杂。
这篇文章就是通过组合类来替换上面嵌套内置类型开发模式,简化开发代码的复杂度。

2.使用嵌套内置类型开发业务示例

下面通过一个使用嵌套内置类型实现业务逻辑,体验下它随着业务越来越复杂,操作嵌套内置类型数据代码也变得复杂。

2.1.第一版需求

在一个考试系统中,实现增加学生信息,添加学生所有考试分数,计算学生的平均分。

# 创建一个计算学生平均分的类
class SimpleGradebook:def __init__(self):# 初始化一个字典存放学生信息和分数self._grades = {}# 创建学生对象def add_student(self, name):self._grades[name] = []# 添加学生分数def report_grade(self, name, score):self._grades[name].append(score)# 计算平均分数def average_grade(self, name):grades = self._grades[name]return sum(grades) / len(grades)book = SimpleGradebook()
book.add_student('zhansan')
book.report_grade('zhansan', 90)
book.report_grade('zhansan', 95)
book.report_grade('zhansan', 99)print(book.average_grade('zhansan'))

运行上面的代码,输出了学生的平均分

94.66666666666667

2.2.第二版需求

在第一版需求上添加新的需求,将学生的学分按照课程添加,同时在每次考试科目里增加权重,根据科目的权重计算出平均分。

  • 新需求的复杂度增加了,存储数据的内置类型嵌套层级也增加了复杂度。{‘name’:{‘subject’:[(score, weight)]}}
  • 添加学生分数的方法,要增加科目、权重属性,将数据封装到嵌套的内置类型中
  • 计算平均分的方法为了处理嵌套内置类型的数据代码变得非常复杂
from collections import defaultdict
class WeightGradebook:def __init__(self):self._grades = {}# defaultdict返回一个字典,_grades字典就是一个内置类型的嵌套结构:{'name':{'subject':[(score, weight)]}}def add_student(self, name):self._grades[name] = defaultdict(list)def report_grades(self, name, subject, score, weight):# 根据学生名称获取所有的课程bysubject = self._grades[name]# 获取某一个课程的分数和权重grade_list = bysubject[subject]# 添加分数和权重grade_list.append((score, weight))# 嵌套内置类型会使业务逻辑变得复杂def average_grade(self, name):by_subject = self._grades[name]score_sum, score_count = 0, 0for subject, scores in by_subject.items():subject_avg, total_wight = 0, 0for score, weight in scores:subject_avg += score * weighttotal_wight += weightscore_sum += subject_avg / total_wightscore_count += 1return score_sum / score_countbook = WeightGradebook()
book.add_student('zhangsan')
book.report_grades('zhangsan', 'Math', 75, 0.05)
book.report_grades('zhangsan', 'Math', 85, 0.09)
book.report_grades('zhangsan', 'Math', 60, 3.05)
print(book.average_grade('zhangsan'))

3.多层嵌套内置类型重构为类体系

使用嵌套类重构代码,它的设计思想归结到一点,就是用类对象替代内置类型存储数据。
嵌套类重构开发思路:

  • 拆分对象,将数据对象拆分到类对象。
    • 课程类对象存储课程分数和权重
    • 学生类对象存储学生各科目的成绩

1.构建底层数据结构

先从依赖书的最底层开始,考虑怎么存储某科目的单次考试成绩与权重。由于分数不需要修改,因此可以使用元组记录考试成绩和权重。
下面来看一个例子

grades = []
grades.append((98, 0.78))
grades.append((88, 0.12))
total = sum(score * weight for score, weight in grades)
total_weight = sum(weight for _, weight in grades)
average_grade = total / total_weight

上面的例子,在计算total_weight时遍历grades元组score不需要因此使用_忽律,并且元组传参使用数字,不容易看出对应的是哪个参数。因此我们可以使用具名元组类代替普通的元组,存储分数和权重。

from collections import namedtuple
Grade = namedtuple('Grade', ('score', 'weight'))

2.创建类

我们的数据中包含了学生对象、课程对象、分数权重对象、其中分数和权重非常简单不需要创建类,用一个数组来存储数据。其余的每个对象都对应的创建一个类存储对象数据。

创建课程类

class Subject:def __init__(self):# 创建列表存储课程分数和权重self._grades = []# 添加分数和权重def report_grade(self, score, weight):self._grades.append(Grade(score, weight))# 计算平均分def average_grade(self):total, total_weight = 0, 0for grade in self._grades:total += grade.score * grade.weighttotal_weight += grade.weightreturn total / total_weight

创建学生类

class Student:def __init__(self):# 组合类,将课程类对象组合到学生类中,创建一个Subject类型的字典。self._subjects = defaultdict(Subject)# 获取课程def get_subject(self, name):return self._subjects[name]# 计算平均分def average_grade(self):total, count = 0, 0for subject in self._subjects.values():total += subject.average_grade()count += 1return total / count

创建成绩册类
将学生名称和学生对象关联

class Gradebook:def __init__(self):self._students = defaultdict(Student)def get_student(self, name):return self._students[name]

调用重构的组合类代码

book = Gradebook()
albert = book.get_student('zhangsan')
math = albert.get_subject('Math')
math.report_grade(75, 0.01)
math.report_grade(89, 0.5)
gym = albert.get_subject('Gym')
gym.report_grade(89, 1.9)
gym.report_grade(79, 0.3)
print(albert.average_grade())

输出结果

88.18092691622104

相关内容

热门资讯

浙江高考改革试点方案公布 外语... 太阳教育网讯 浙江省深化高校考试招生制度综合改革试点方案(方案解读)公布。方案规定,语文、数学考试于...
浙江高考改革试点方案公布 扩大...  太阳教育网讯 浙江省深化高校考试招生制度综合改革试点方案(方案解读)公布。据介绍,本次改革近期主要...
临朝称制是什么意思?出现于什么... 古时后宫是不能上厅堂的,所以后妃要掌权就要"临朝",从秦始皇开始皇帝的命令专称"制"、布告公文称"诰...
盘点历史上临朝称制的六位女性,... 在我们的印象中,权力似乎从来都是男人的事情,尤其是古代社会,男尊女卑,女人更没有什么地位,可是中国历...
“AI+低空经济”如何与职教融... 大象新闻记者 梁新慧 12月27日,由河南省中原职业教育研究院职业技能培训指导中心、河南省地理信息...