一、尽量用辅助类来维护程序的状态
如下,用字典存储简单数据
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('ss') book.report_grade('ss', 90) book.report_grade('ss', 100) print(book.average_grade('ss'))
如下示例,多层字典结构,代码变得负责且难读
class SimpleGradebook(): def __init__(self): self.__grades = {} def add_student(self, name): self.__grades[name] = {} # 一个学生的成绩加入科目分类,所以用字典存储 def report_grade(self, name, subject, score): by_subject = self.__grades[name] grade_list = by_subject.setdefault(subject, []) # 存在该科目则返回已有列表,不存在则返回一个空列表 grade_list.append(score) 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 book = SimpleGradebook() book.add_student('ss') book.report_grade('ss', 'Math', 90) book.report_grade('ss', 'Math', 100) print(book.average_grade('ss'))
使用嵌套结构重构类,书上的代码有错,以下是github上本书第二版的最新示例代码
from collections import namedtuple, defaultdict Grade = namedtuple('Grade', ('score', 'weight')) # 具名元组 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, 0 for grade in self._grades: total += grade.score * grade.weight total_weight += grade.weight return total / total_weight class Student: # 学生的类,包含各项课程 def __init__(self): self._subjects = defaultdict(Subject) def get_subject(self, name): 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: # 所有学生成绩的容器类,以学生的名字为键 def __init__(self): self._students = defaultdict(Student) def get_student(self, name): return self._students[name] book = Gradebook() albert = book.get_student('ss') math = albert.get_subject('Math') math.report_grade(75, 0.05) math.report_grade(65, 0.15) math.report_grade(70, 0.80) gym = albert.get_subject('Gym') gym.report_grade(100, 0.40) gym.report_grade(85, 0.60) print(albert.average_grade())
二、简单接口应该接受函数,而不是类的实例
简单接口使用函数,不要用类;
通过__call__方法,可以使类实例像函数一样被调用
如果需要保存状态,应该定义新的类,而不是带状态的闭包。
三、以@classmethod形式的多态去通用地构建对象
pass
四、用super初始化父类
pass
五、多用public属性,少用private属性
pass
六、从collections.abc中继承基类
简单子类可以直接从python的标准类型中继承(如list,dict,set,tuple等)
collections.abc中有很多基类