一、尽量用辅助类来维护程序的状态

如下,用字典存储简单数据

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中有很多基类

《Effective Python》笔记——第3章 类与继承的更多相关文章

  1. JVM学习笔记-第六章-类文件结构

    JVM学习笔记-第六章-类文件结构 6.3 Class类文件的结构 本章中,笔者只是通俗地将任意一个有效的类或接口锁应当满足的格式称为"Class文件格式",实际上它完全不需要以磁 ...

  2. [Effective JavaScript 笔记]第3章:使用函数--个人总结

    前言 这一章把平时会用到,但不会深究的知识点,分开细化地讲解了.里面很多内容在高3等基础内容里,也有很多讲到.但由于本身书籍的篇幅较大,很容易忽视对应的小知识点.这章里的许多小提示都很有帮助,特别是在 ...

  3. C++ primer plus读书笔记——第13章 类继承

    第13章 类继承 1. 如果购买厂商的C库,除非厂商提供库函数的源代码,否则您将无法根据自己的需求,对函数进行扩展或修改.但如果是类库,只要其提供了类方法的头文件和编译后的代码,仍可以使用库中的类派生 ...

  4. C++ primer plus读书笔记——第12章 类和动态内存分配

    第12章 类和动态内存分配 1. 静态数据成员在类声明中声明,在包含类方法的文件中初始化.初始化时使用作用域运算符来指出静态成员所属的类.但如果静态成员是整形或枚举型const,则可以在类声明中初始化 ...

  5. C#图解教程读书笔记(第7章 类和继承)

    1.所有的类都继承自object 2.如何隐藏基类的成员 要隐藏一个继承的数据成员,需要声明一个新的相同类型的成员,并使用相同的名称. 通过在派生类中声明新的带有相同签名的函数成员,可以隐藏或掩盖继承 ...

  6. python 静态方法,类方法 ,类的继承

    转自:  http://cowboy.1988.blog.163.com/blog/static/75105798201091141521583/ 1.关于定义类的一些奇特之处  今天在Python中 ...

  7. C#图解教程 第七章 类和继承

    类和继承 类继承访问继承的成员所有类都派生自object类屏蔽基类的成员基类访问使用基类的引用 虚方法和覆写方法覆写标记为override的方法覆盖其他成员类型 构造函数的执行 构造函数初始化语句类访 ...

  8. 【python系统学习14】类的继承与创新

    目录: 目录: [toc] 类的继承 子类和父类 继承的写法 继承示例 父类可以被无限个子类所继承 子类实例可调用父类属性和方法 类的始祖(根类) 根类 - object 实例归属判断 - isins ...

  9. [Effective Java 读书笔记] 第三章类和接口 第二十-二十一条

    第二十条 用函数对象表示策略 函数指针(JAVA的函数指针,是指使用对象的引用来作为参数,传递给另一个对象的方法)主要用来实现策略模式,为了在JAVA中实现这种模式,要申明一个接口来表示该策略,并为每 ...

随机推荐

  1. 关于MySQL导入数据到elasticsearch的小工具logstash

    logstash核心配置文件pipelines.yml #注:此处的 - 必须顶格写必须!!! - pipeline.id: invitation #下面路径配置的是你同步数据是的字段映射关系 pat ...

  2. FileReader()读取文件、图片上传预览

    前言 FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据. 其中File对象可以是来自用户 ...

  3. .Net 线程安全集合

    .Net 提供了基于生产-消费模式的集合类,这些集合对多线程访问安全,定义在System.Collections.Concurrent名称空间中.这个名称空间中包括基础接口IProduceConsum ...

  4. linux 下安装PostgreSql 并配置远程访问

    1.官网下载PostgreSql 安装包 (https://www.enterprisedb.com/downloads/postgres-postgresql-downloads) 我下载的是 9. ...

  5. 【reverse】逆向2 寄存器与内存

    [reverse]逆向2 寄存器与内存 1.通用寄存器 主要用途其实没必要记下来,因为只是CPU建议你这么做. 寄存器需要按照顺序被下来 32位就是可以存32个0或1 所以存储范围就是0-0xFFFF ...

  6. 话说C#程序员人手一个ORM

    话说C#程序员人手一个ORM,确实没有必要再写ORM了,不过我的ORM并不是新的,是从DBHelper演化过来的,算是DBHelper魔改版. 目前流行的ORM有EF.Dapper.SqlSugar. ...

  7. NGINX的动静分离;什么是负载均衡

    目录 一:动静分离 二:负载均衡 一:动静分离 动静分离是指在 web 服务器架构中,将静态页面与动态页面或者静态内容接口和动态内容接口分开不同系统访问的架构设计方法,进而提示整个服务的访问性和可维护 ...

  8. K8s 资源范围管理对象 LimitRange

    默认情况下如果创建一个 Pod 没有设置 Limits 和 Requests 对其加以限制,那么这个 Pod 可能能够使用 Kubernetes 集群中全部资源, 但是每创建 Pod 资源时都加上这个 ...

  9. python代码加注释--6

    备注:#用来注释代码,#后面的内容会被python解释器忽略

  10. MySQL开发篇,存储引擎的选择真的很重要吗?

    前言 谁说MySQL查询千万级别的数据很拉跨?我今天就要好好的和你拉拉家常,畅谈到深夜,一起过除夕!这篇文章也是年前的最后一篇,希望能带给大家些许收获,不知不觉查找文档和参考实体书籍就写了这么多,自己 ...