美文网首页
第22条:尽量用辅助类来维护程序状态,而不是字典和元组

第22条:尽量用辅助类来维护程序状态,而不是字典和元组

作者: 小懒额 | 来源:发表于2018-05-29 08:23 被阅读0次

现在如果用一段代码来实现通过学生成绩求出学生平均成绩,一般会这样做:

class SimpleGradebook(object):
    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)

这里,使用字典来保存学生的姓名和对应的多次成绩,可以看出,在 Python 中,字典很好的处理了数据的动态变化。这时,如果需要把成绩细化成不同科目的成绩,就需要去保存科目信息了。

class SubjectGradebook(object):
    def __init__(self):
        self._grades = {}

    def add_student(self, name):
        self._grades[name] = {}

    def report_grade(self, name, subject, grade):
        by_subject = self._grades[name]
        grade_list = by_subject.setdefault(subject, [])
        grade_list.append(grade)

    def average_grade(self, name):
        by_subject = self._grades[name]
        total, count = 0, 0
        for grades in by_subject.values():
            total += sum(grades)
            count += len(grades)
        return total/count

这里的结构有所变化,原先用来保存多次成绩的列表被替换成了字典,和保存成绩的字典形成了两层嵌套。也就是成绩的字典里面保存了学生姓名和对应的科目成绩字典,科目成绩字典保存了不同科目和对应科目的多次成绩。这样改,没有太麻烦,看上去还过得去。

现在,如果给每科添加一个权重,不同考试所占权重不同,比如平时考试权重较低,期中期末考试权重较高,在计算平均分时又会有变化。

class WeightGradeBook(object):
    def __init__(self):
        self._grades = {}

    def add_student(self, name):
        self._grades[name] = {}

    def report_grade(self, name, subject, score, weight):
        by_subject = self._grades[name]
        grade_list = by_subject.setdefault(subject, [])
        grade_list.append(score, weight)

    def average_grade(self, name):
        by_subject = self._grades[name]
        total, total_weight = 0, 0
        for grades in by_subject.values():
            total += grades[0]*grades[1]
            total_weight += (grades[1])

        return total / total_weight

因为每次成绩都有一个权重,这样在保存成绩的时候还要把权重一起加进去,可以使用元组来实现这个需求。也就是原先保存多次成绩的列表中的元素变成了一个个元组。这样可以实现,但是代码看上去就不是很清晰,而且多种结构冗在一起,不利于维护。

所以,我们可以使用辅助类来做这些数据,把不同数据用一个个类来分开处理。

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

class Subject(object):
    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, 0
        for grade in self._grades:
            total += grade.score * grade.weight
            total_weight += grade.weight
        return total / total_weight


class Student(object):
    def __init__(self):
        self._subjects = {}

    def subject(self, name):
        if name not in self._subjects:
            self._subjects[name] = Subject()
        return self._subjects[name]

    def average_grade(self):
        total, count = 0, 0
        for subject in self._subjects.values():
            total += subject.average_grade()
            count += 1
        return total/count

class GradeBook(object):
    def __init__(self):
        self._students = {}

    def student(self, name):
        if name not in self._students:
            self._students[name] = Student()
        return self._students[name]

这里用到了一个 nametuple,一般来说,元组中的元素超过两个的时候,元组中的元素再进行扩张的时候,就很难理解每个元素的作用,这样用 nametuple 来保存,便于理解。

可以看到,对于不同的数据,都使用了辅助类来实现,解除了之前代码中的多重嵌套,让代码看上去很清晰,用起来也是很方便。

book = GradeBook()
user = book.student('xiaoming')
math = user.subject('math')
math.report_grade(90, 0.1)
math.report_grade(100, 0.1)
print(user.average_grade())
>>>
95.0

相关文章

  • 第22条:尽量用辅助类来维护程序状态,而不是字典和元组

    现在如果用一段代码来实现通过学生成绩求出学生平均成绩,一般会这样做: 这里,使用字典来保存学生的姓名和对应的多次成...

  • 高效 Python 代码——类与继承

    一、用辅助类(而不是字典)来维护程序的状态 Python 内置的字典类型可以很好地保存某个对象在其生命周期中的(动...

  • 【Python_67-70】元组【b站搬运_子木】

    什么是元组? 元组不可增删改(是不可变序列!列表和字典可变) 元组用()定义 vs 列表用 [ ] 定义 可变序列...

  • python常用数据类型元组/字典/列表&运算符

    第5篇分享 常用的数据类型: 元组、列表、字典 元组:tuple 1、用()括起来的数据2、元组支持任何类型的数据...

  • Python02

    字典 创建字典:使用大括号,用冒号分隔键和值访问、插入、设置元素的语法与列表和元组一样用in判断字典中是否存在某个...

  • 数据结构

    序列(如列表和元组)、映射(如字典)以及集合(set)是三类主要的数据结构(也称为容器)。 序列(列表、元组和字符...

  • Python学习总结

    数据类型 循环和分支 列表 元组、字符串 序列 函数 字典 文件 异常处理 类和对象 模块

  • 字典值与元组的值交换

    定义一个函数,能够输入字典和元组。将字典的值(value) 和 元组的值交换, 交换结束后,打印并且返回 字典和元祖。

  • 元组和字典

    一,元组(tuple) 元组是不可变的列表,列表中除了课表操作外,其他的操作都适用于元组 1.元组的声明(元组名=...

  • 元组和字典

    元组不能修改,只能合并,用小括号()表示corse1=(1,2,5) corse2=(5,8,0)corse3...

网友评论

      本文标题:第22条:尽量用辅助类来维护程序状态,而不是字典和元组

      本文链接:https://www.haomeiwen.com/subject/cbkojftx.html