流畅的python读书笔记-第十章-继承优缺点
继承的优缺点
推出继承的初衷是让新手顺利使用只有专家才能设计出来的框架。
——Alan Kay
子类化内置类型很麻烦 (如 list 或 dict)) ,别搞这种
- 直接子类化内置类型(如 dict、list 或 str)容易出错,因为内置类型的 方法通常会忽略用户覆盖的方法。
- 不要子类化内置类型,用户自己定义的类应该继承 collections 模块的类,
- 例如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读书笔记-第十章-继承优缺点的更多相关文章
- 流畅的Python读书笔记(二)
2.1 可变序列与不可变序列 可变序列 list. bytearray. array.array. collections.deque 和 memoryview. 不可变序列 tuple. str 和 ...
- 流畅的python 读书笔记 第二章 序列构成的数组 列表推导
列表推导是构建列表(list)的快捷方式,而生成器表达式则可以用来创建其他任何类型的序列.如果你的代码里并不经常使用它们,那么很可能你错过了许多写出可读性更好且更高效的代码的机会. 2.2.1 列表推 ...
- Web Scraping with Python读书笔记及思考
Web Scraping with Python读书笔记 标签(空格分隔): web scraping ,python 做数据抓取一定一定要明确:抓取\解析数据不是目的,目的是对数据的利用 一般的数据 ...
- Java Concurrency in Practice 读书笔记 第十章
粗略看完<Java Concurrency in Practice>这部书,确实是多线程/并发编程的一本好书.里面对各种并发的技术解释得比较透彻,虽然是面向Java的,但很多概念在其他语言 ...
- 《利用python进行数据分析》读书笔记--第十章 时间序列(三)
7.时间序列绘图 pandas时间序列的绘图功能在日期格式化方面比matplotlib原生的要好. #-*- coding:utf-8 -*- import numpy as np import pa ...
- python读书笔记-《A Byte of Python》中文第三版后半部分
编辑器:windows,linux 不要用notepad,缩进糟糕 -------------- 5.18缩进 同一层次的语句必须有相同的缩进.每一组这样的语句称为一个块. i = 5 2 prin ...
- OK - A byte of python - 读书笔记
看这本书的目的:再熟悉基本概念. 大部分都是知道,但是需要 明确 出来的 概念. - 欢迎吐槽错误,非常感谢. <A byte of python> - THIS 1. 组织行 - 形式: ...
- Python学习笔记8-类的继承 、深度优先、广度优先
Python 类声明 语法: class 类名: 类体 例: #--encoding:utf-8-- # class AddressBookEntity: myVersion=0.1 def __in ...
- 【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 ...
随机推荐
- 曹工说Redis源码(2)-- redis server 启动过程解析及简单c语言基础知识补充
文章导航 Redis源码系列的初衷,是帮助我们更好地理解Redis,更懂Redis,而怎么才能懂,光看是不够的,建议跟着下面的这一篇,把环境搭建起来,后续可以自己阅读源码,或者跟着我这边一起阅读.由于 ...
- 大数据hadoop安装
hadoop集群搭建--CentOS部署Hadoop服务 在了解了Hadoop的相关知识后,接下来就是Hadoop环境的搭建,搭建Hadoop环境是正式学习大数据的开始,接下来就开始搭建环境!我们用到 ...
- Centos装机预备技能
装机预备技能 1.1问题 本例要求安装一台可用的KVM服务器: RHEL与Cent ...
- Linux系统安装java jdk
1)下载地址: https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 我这里下载的是 ...
- 微信小程序H5预览页面框架(二维码不隐藏)
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...
- Java第六天,API中常用的类,StringBuffer、StringBuilder、包装类、System类的使用
System (1)这个类中有很多可以获取系统信息的类. public class SystemLearn { public static void main(String[] args) { lon ...
- String 对象-->大小比较
1.定义和用法 规则:从左至右依次对比相同下标处的字符,当两个字符不相等时,哪个字符的ASCII值大,那就哪个字符串就大. 返回值为1,左边大于右边 返回值为-1,右边大于左边 返回值为0,则相等 举 ...
- fork()系统调用的理解
系统调用fork()用于创建一个新进程.我们可以通过下面的代码来理解,最好是能自己敲一遍运行验证. #include<stdio.h> #include<stdlib.h> ...
- 数据结构和算法(Golang实现)(19)排序算法-冒泡排序
冒泡排序 冒泡排序是大多数人学的第一种排序算法,在面试中,也是问的最多的一种,有时候还要求手写排序代码,因为比较简单. 冒泡排序属于交换类的排序算法. 一.算法介绍 现在有一堆乱序的数,比如:5 9 ...
- AJ学IOS(01) UI之Hello World与加法计算器
不多说,AJ分享,必须精品 这两个一个是HelloWorld(左边) 另一个是 加法计算器(右边)的截图. 先运行第一个 程序看看效果 1.打开Xcode(没有哦mac系统的没有xcode的帮你们默哀 ...