类与继承
尽量用辅助类来维护程序的状态,而不要用字典和元组
# Example 10
grades = []
grades.append((95, 0.45, 'Great job'))
grades.append((85, 0.55, 'Better next time'))
total = sum(score * weight for score, weight, _ in grades) # 遍历三元素元组的列表
total_weight = sum(weight for _, weight, _ in grades)
average_grade = total / total_weight
print(average_grade)
#把嵌套结构改写成类
# Example 12
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
# Example 13
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
# Example 14
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]
# Example 15
book = Gradebook()
albert = book.student('Albert Einstein')
math = albert.subject('Math')
math.report_grade(80, 0.10)
math.report_grade(80, 0.10)
math.report_grade(70, 0.80)
gym = albert.subject('Gym')
gym.report_grade(100, 0.40)
gym.report_grade(85, 0.60)
print(albert.average_grade())
代码量增加了很多,但更容易理解。
- 不要使用包含其他字典的字典和过长的元组
- namedtuple
- 复杂的字典,拆解为多个辅助类
简单的接口应该接受函数,而不是类的实例
函数是一级对象,可以被传递和引用,可以充当挂钩(hook)。
# Example 8
class BetterCountMissing(object):
def __init__(self):
self.added = 0
def __call__(self): #通过__call__方法,可以使类的实例能够像普通函数那样得到调用
self.added += 1
return 0
counter = BetterCountMissing()
counter()
assert callable(counter)
如果要用函数来保存状态,那就应该定义新的类,并令其实现call方法。
24 以@classmethod形式的多态去通用地构建对象
没看懂,先跳过
25 用super初始化父类
主要是在多重继承中,考虑初始化顺序时使用吧。一般用不动
26 只在使用Mix-in组件制作工具类时进行多重继承
先跳过
27 多用public属性,少用private属性
比较简单,无需多言。
28 继承collections.abc以实现自定义的容器类型
- 如果定制的子类比较简单,可直接从Python的容器类型中继承
- 编写自制的容器类型时,可从collections。abc模块的抽象基类中继承,那些基类能够确保我们的子类具备适当的接口及行为。