• effective python 读书笔记-第22条: 尽量用辅助类来维护程序的状态,而不要用字典


    第22条: 尽量用辅助类来维护程序的状态,而不要用字典

    带着问题学习

    1. 如何使用字段维护程序的状态?
    2. 如何使用辅助类为辅程序的状态?
    3. 有没有更好的方式?

    总结

    • 1.1 使用字典维护程序的状态(简单示例)
    需求:
    记录学生的名字,记录学生对应的科目(假设一个科目)的多次成绩
    
    
    代码实现:
    class SimpleGradebook(object):
        def __init__(self):
            self.grades = {}
    
        def add_student(self, name):
            if name in self.grades:
                raise ValueError('no named {}'.format(name))
            self.grades[name] = []
    
        def report_grade(self, name, score):
            if name not in self.grades:
                raise ValueError('no named {}'.format(name))
            self.grades[name].append(score)
    
        def average_grade(self, name):
            grades = self.grades[name]
            return sum(grades) / len(grades)
    
    
    book = SimpleGradebook()
    book.add_student('xiaoming')
    book.report_grade('xiaoming', 90)
    book.report_grade('xiaoming', 80)
    print(book.average_grade('xiaoming'))
    # 85
    
    book.add_student('liming')
    book.report_grade('liming', 60)
    book.report_grade('liming', 65)
    print(book.average_grade('liming'))
    #62
    
    print(book.grades)
    # {'liming': [60, 65], 'xiaoming': [90, 80]}
    
    
    • 1.2 使用字典维护程序的状态(中等复杂度示例)
    # 记录每个学生对应的各科的多次成绩,最后求所有成绩的平均成绩
    class BySubjectGradebook(object):
        def __init__(self):
            self.grades = {}
    
        def add_student(self, name):
            if name in self.grades:
                raise ValueError('no named {}'.format(name))
            self.grades[name] = {}
    
        def report_grade(self, name, subject, grade):
            if name not in self.grades:
                raise ValueError('no named {}'.format(name))
            by_subject = self.grades[name]
            grade_list = by_subject.setdefault(subject, [])
            grade_list.append(grade)
    
        def average_grade_of_all_subjects(self, name):
            subjects_grades = self.grades[name]
            total, count = 0, 0
            for grades in subjects_grades.values():
                total += sum(grades)
                count += len(grades)
            return total / count
    
    
    book = BySubjectGradebook()
    book.add_student('xiaoming')
    book.report_grade('xiaoming','Math', 90)
    book.report_grade('xiaoming', 'Math',80)
    book.report_grade('xiaoming', 'Gym',70)
    book.report_grade('xiaoming', 'Gym',80)
    print(book.average_grade_of_all_subjects('xiaoming'))
    # 80
    
    
    • 1.3 使用字典维护程序的状态(比较复杂,示例)
    # 记录每个学生对应的各科成绩不同考试对应的成绩与权重比例
    class WeightGradebook(object):
        def __init__(self):
            self.grades = {}
    
        def add_student(self, name):
            if name in self.grades:
                raise ValueError('no named {}'.format(name))
            self.grades[name] = {}
    
        def report_grade(self, name, subject, score, weight):
            if name not in self.grades:
                raise ValueError('no named {}'.format(name))
            by_subject = self.grades[name]
            grade_list = by_subject.setdefault(subject, [])
            grade_list.append((score, weight))
    
        def average_grade_of_all_subjects(self, name):
            subjects_grades = self.grades[name]
            score_sum, subject_count = 0, 0
            for subject, scores in subjects_grades.items():
                subject_avg, subject_total_score, total_weight = 0, 0, 0
                for score, weight in scores:
                    subject_total_score += score*weight
                    total_weight += weight
                subject_avg = subject_total_score / total_weight
                score_sum += subject_avg
                subject_count += 1
            print(subject_count)
            return score_sum / subject_count
    
    
    book = WeightGradebook()
    book.add_student('xiaoming')
    book.report_grade('xiaoming', 'Math', 90, 0.6)
    book.report_grade('xiaoming', 'Math', 80, 0.4)
    book.report_grade('xiaoming', 'Gym', 70, 0.7)
    book.report_grade('xiaoming', 'Gym', 80, 0.3)
    print(book.grades)
    print(book.average_grade_of_all_subjects('xiaoming'))
    # {'xiaoming': {'Gym': [(70, 0.7), (80, 0.3)], 'Math': [(90, 0.6), (80, 0.4)]}}
    # 2
    # 79.5
    
    
    

    2.1 使用辅助类来维护程序的状态

    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
            print('total:{},total_weight:{}'.format(total, total_weight))
            average_grade = total / total_weight
            print('average_grade:{}'.format(average_grade))
            return average_grade
    
    
    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
            print('total:{},count:{}'.format(total, count))
            return total / count
    
    
    class Gradebook(object):
        def __init__(self):
            self._students = {}
    
        def students(self, name):
            if name not in self._students:
                self._students[name] = Student()
            return self._students[name]
    
    
    book = Gradebook()
    libai = book.students('libai')
    liming = book.students('liming')
    math = libai.subject('math')
    math.report_grade(80, 0.1)
    math.report_grade(90, 0.2)
    print(libai.average_grade())
    # total:26.0,total_weight:0.3
    # average_grade:86.6666666667
    # total:86.6666666667,count:1
    # 86.6666666667
    
    • 2.2 将数据持久化
      将类对的属性与表中的字段对应,不同类型之间的关系可以使用外键关联,按需求实现多对多还是一对多等对应的关系,flask 框架可以使用 继承Model类,然后编写对应的字段

    • 3 总结

    1. 不要使用嵌套字典,不要使用长元组
    2. 简单不可变数据可以用namedtuple
    3. 字典复杂需要拆分为辅助类,比如uwsgi中的spool函数只接受一层级的字典,尽量简单,便宜维护
    仙衣眠云碧岚袍,一襟潇洒,两袖飘飘。玉墨舒心春酝瓢,行也逍遥,坐也逍遥。
  • 相关阅读:
    Redis集群的搭建
    CAS部署在Windows上
    Loadrunner中Error-26612HTTP Status-Cod
    Coneroller执行时候的-26374及-26377错误
    Loadrunner 26377错误
    歌名也好笑
    loadrunner 中Error和failed transaction 的区别
    loadrunner 性能测试报error-27796的解决
    lr11.0负载测试 real-world schedule 与basic schedule的区别是什么
    LR中错误代号为27796的一个解决方法
  • 原文地址:https://www.cnblogs.com/max520liuhu/p/12046581.html
Copyright © 2020-2023  润新知