第22条: 尽量用辅助类来维护程序的状态,而不要用字典
带着问题学习
- 如何使用字段维护程序的状态?
- 如何使用辅助类为辅程序的状态?
- 有没有更好的方式?
总结
- 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 总结
- 不要使用嵌套字典,不要使用长元组
- 简单不可变数据可以用namedtuple
- 字典复杂需要拆分为辅助类,比如uwsgi中的spool函数只接受一层级的字典,尽量简单,便宜维护
来源:https://www.cnblogs.com/max520liuhu/p/12046581.html