继承的优缺点

推出继承的初衷是让新手顺利使用只有专家才能设计出来的框架。
——Alan Kay

子类化内置类型很麻烦 (如 list 或 dict)) ,别搞这种

  1. 直接子类化内置类型(如 dict、list 或 str)容易出错,因为内置类型的 方法通常会忽略用户覆盖的方法。
  2. 不要子类化内置类型,用户自己定义的类应该继承 collections 模块的类,
  3. 例如UserDict、UserList 和 UserString,这些类做了特殊设计,因此易于扩展。
import collections

class DoppelDict2(collections.UserDict):
def __setitem__(self, key, value):
super().__setitem__(key, [value] * 2) dd = DoppelDict2(one=1)
print(dd) dd['two'] = 2
print(dd) dd.update(three=3)
print(dd) class AnswerDict2(collections.UserDict):
def __getitem__(self, key):
return 42 ad = AnswerDict2(a='foo') print(ad["a"])
  • 综上,本节所述的问题只发生在 C 语言实现的内置类型内部的方法委托上,而且只影响 直接继承内置类型的用户自定义类。
  • 如果子类化使用 Python 编写的类,如 UserDict 或 MutableMapping,就不会受此影响。

多重继承和方法解析顺序

class A:
def ping(self):
print('ping:', self) class B(A):
def pong(self):
print('pong:', self) class C(A):
def pong(self):
print('PONG:', self) class D(B, C):
def ping(self):
super().ping()
print('post-ping:', self) def pingpong(self):
self.ping()
super().ping()
self.pong()
super().pong()
C.pong(self) d = D()
d.pong() C.pong(d) #看继承关系
print(D.__mro__)

直接调用 d.pong() 运行的是 B 类中的版本。

Python 能区分 d.pong() 调用的是哪个方法,是因为 Python 会按照特定的顺序遍历继承图。
这个顺序叫方法解析顺序(Method Resolution Order,MRO)。
类都有一个名为__mro__ 的属性,它的值是一个元组,按照方法解析顺序列出各个超类,从当前类一直向上,直到 object 类。D

然而,使用 super() 最安全,也不易过时。调用框架或不受自己控制的类层次结构中的
方法时,尤其适合使用 super()。

多重继承的真实应用

1 多重继承能发挥积极作用。
2 《设计模式:可复用面向对象软件的基础》一书中的适配器模式用的就是多重继承,因此使用多重继承肯定没有错
3(那本书中的其他 22 个设计模式都使用单继承,因此多重继承显然不是灵丹妙药)

处理多重继承

下面是避免把类图搅乱的一些建议。

01. 把接口继承和实现继承区分开

使用多重继承时,一定要明确一开始为什么创建子类。主要原因可能有:

继承接口,创建子类型,实现“是什么”关系
继承实现,通过重用避免代码重复

其实这两条经常同时出现,不过只要可能,一定要明确意图。通过继承重用代码是实
现细节,通常可以换用组合和委托模式。而接口继承则是框架的支柱。

02. 使用抽象基类显式表示接口

现代的 Python 中,如果类的作用是定义接口,应该明确把它定义为抽象基类。Python
3.4 及以上的版本中,我们要创建 abc.ABC 或其他抽象基类的子类

python没有interface这种定义

03. 通过混入重用代码

  • 一个类的作用是为多个不相关的子类提供方法实现
  • 应该把那个类明确地定义为混入类(mixin class)
  • 从概念上讲,混入不定义新类型,只是打包方法,便于重用。
  • 混入类绝对不能实例化,而且具体类不能只继承混入类。
  • 混入类应该提供某方面的特定行为,只实现少量关系非常紧密的方法。

04. 在名称中明确指明混入

  • 因为在 Python 中没有把类声明为混入的正规方式,所以强烈推荐在名称中加入...Mixin 后缀。
  • Tkinter 没有采纳这个建议,如果采纳的话,XView 会变成XViewMixin,Pack 会变成 PackMixin

05. 为用户提供聚合类

class Widget(BaseWidget, Pack, Place, Grid):
"""Internal class.
Base class for a widget which can be positioned with the
geometry managers Pack, Place or Grid."""
pass

Widget 类的定义体是空的,但是这个类提供了有用的服务:

把四个超类结合在一起,这样需要创建新小组件的用户无需记住全部混入,也不用担心声明 class 语句时有没有遵守特定的顺序。

08. “优先使用对象组合,而不是类继承”

这句话引自《设计模式:可复用面向对象软件的基础》一书, 这是我能提供的最佳
建议。

熟悉继承之后,就太容易过度使用它了。出于对秩序的诉求,我们喜欢按整洁
的层次结构放置物品,程序员更是乐此不疲。

即便是单继承,这个原则也能提升灵活性,因为子类化是
一种紧耦合,而且较高的继承树容易倒。

继承在Django的应用

page 417 这里有些复杂,等我牛掰了再来看

总结

collections.abc 模块中相应的抽象基类
多重继承这把双刃剑。首先,我们说明了 mro 类属性中蕴藏的方法解析顺序,有了这一机制,继承方法的名称不再会发生冲突
不要子类化内置类型,用户自己定义的类应该继承 collections 模块的类

流畅的python读书笔记-第十章-继承优缺点的更多相关文章

  1. 流畅的Python读书笔记(二)

    2.1 可变序列与不可变序列 可变序列 list. bytearray. array.array. collections.deque 和 memoryview. 不可变序列 tuple. str 和 ...

  2. 流畅的python 读书笔记 第二章 序列构成的数组 列表推导

    列表推导是构建列表(list)的快捷方式,而生成器表达式则可以用来创建其他任何类型的序列.如果你的代码里并不经常使用它们,那么很可能你错过了许多写出可读性更好且更高效的代码的机会. 2.2.1 列表推 ...

  3. Web Scraping with Python读书笔记及思考

    Web Scraping with Python读书笔记 标签(空格分隔): web scraping ,python 做数据抓取一定一定要明确:抓取\解析数据不是目的,目的是对数据的利用 一般的数据 ...

  4. Java Concurrency in Practice 读书笔记 第十章

    粗略看完<Java Concurrency in Practice>这部书,确实是多线程/并发编程的一本好书.里面对各种并发的技术解释得比较透彻,虽然是面向Java的,但很多概念在其他语言 ...

  5. 《利用python进行数据分析》读书笔记--第十章 时间序列(三)

    7.时间序列绘图 pandas时间序列的绘图功能在日期格式化方面比matplotlib原生的要好. #-*- coding:utf-8 -*- import numpy as np import pa ...

  6. python读书笔记-《A Byte of Python》中文第三版后半部分

    编辑器:windows,linux 不要用notepad,缩进糟糕 -------------- 5.18缩进 同一层次的语句必须有相同的缩进.每一组这样的语句称为一个块. i = 5 2  prin ...

  7. OK - A byte of python - 读书笔记

    看这本书的目的:再熟悉基本概念. 大部分都是知道,但是需要 明确 出来的 概念. - 欢迎吐槽错误,非常感谢. <A byte of python> - THIS 1. 组织行 - 形式: ...

  8. Python学习笔记8-类的继承 、深度优先、广度优先

    Python 类声明 语法: class 类名: 类体 例: #--encoding:utf-8-- # class AddressBookEntity: myVersion=0.1 def __in ...

  9. 【updating】python读书笔记-The Django Book2.0(for django1.4)

    原文:http://www.djangobook.com/en/2.0/frontmatter.html 译文:http://djangobook.py3k.cn/2.0/ 或者http://docs ...

随机推荐

  1. Java学习笔记--Arrays

    Arrays(数组工具类)常用方法 Arrays.toString(int[] a)方法  ------->  返回类型为String,可以用来产生数组的可打印表示,避免了用循环依次读取数组值进 ...

  2. Linux - Ubuntu下执行apt-get update报错:Some index files failed to download. They have been ignored, or old ones used instead.

    报错命令 root@ubuntu:/etc/apt# apt-get update Err: http://mirrors.aliyun.com/ubuntu trusty InRelease Cou ...

  3. 微信小程序placeholder设置自定义颜色

    原地址链接:https://blog.csdn.net/august_leo/article/details/80877382 这是微信小程序input组件的官方文档描述,下图红框里的placehol ...

  4. go语言goroutine

    Go语言goroutine 在别的语言里想要在一个程序中实现多任务,如python,python实现多任务可以使用多进程.多线程.携程.但多进程占用资源,多线程无法发挥多核的优势(GIL),pytho ...

  5. MTK Android Driver :Battery电池曲线

    MTK Android Driver :battery电池曲线 1.配置文件位置: CUSTOM_KERNEL_BATTERY= battery mediatek\custom\\kernel\bat ...

  6. 《闲扯Redis四》List数据类型底层编码转换

    一.前言 Redis 提供了5种数据类型:String(字符串).Hash(哈希).List(列表).Set(集合).Zset(有序集合),理解每种数据类型的特点对于redis的开发和运维非常重要. ...

  7. PHP程序员的能力水平层次(二)

    PHPer的定义:PHPer是以PHP程序编写为主要工作,其他方面略有涉及的一种职业人士,大家所说的程序猿. 对PHPer的等级划分 PHP 爱好者 (半个PHPer) PHP 初学者 (PHP Be ...

  8. tf.nn.relu 激活函数

    tf.nn.relu(features, name = None) 计算校正线性:max(features, 0) 参数: features:一个Tensor.必须是下列类型之一:float32,fl ...

  9. readelf命令

    //查看文件头信息 readelf -h [file] //查看文件依赖的动态库 readelf -d [file] //查看文件中的符号 readelf -s [file]

  10. 数据结构和算法(Golang实现)(1)简单入门Golang-前言

    数据结构和算法在计算机科学里,有非常重要的地位.此系列文章尝试使用 Golang 编程语言来实现各种数据结构和算法,并且适当进行算法分析. 我们会先简单学习一下Golang,然后进入计算机程序世界的第 ...