浅析Python中的多重继承


Posted in Python onApril 28, 2015

继承是面向对象编程的一个重要的方式,因为通过继承,子类就可以扩展父类的功能。

回忆一下Animal类层次的设计,假设我们要实现以下4种动物:

  1.     Dog - 狗狗;
  2.     Bat - 蝙蝠;
  3.     Parrot - 鹦鹉;
  4.     Ostrich - 鸵鸟。

如果按照哺乳动物和鸟类归类,我们可以设计出这样的类的层次:

浅析Python中的多重继承

但是如果按照“能跑”和“能飞”来归类,我们就应该设计出这样的类的层次:

浅析Python中的多重继承

如果要把上面的两种分类都包含进来,我们就得设计更多的层次:

  •     哺乳类:能跑的哺乳类,能飞的哺乳类;
  •     鸟类:能跑的鸟类,能飞的鸟类。

这么一来,类的层次就复杂了:

浅析Python中的多重继承

如果要再增加“宠物类”和“非宠物类”,这么搞下去,类的数量会呈指数增长,很明显这样设计是不行的。

正确的做法是采用多重继承。首先,主要的类层次仍按照哺乳类和鸟类设计:

class Animal(object):
  pass

# 大类:
class Mammal(Animal):
  pass

class Bird(Animal):
  pass

# 各种动物:
class Dog(Mammal):
  pass

class Bat(Mammal):
  pass

class Parrot(Bird):
  pass

class Ostrich(Bird):
  pass

现在,我们要给动物再加上Runnable和Flyable的功能,只需要先定义好Runnable和Flyable的类:

class Runnable(object):
  def run(self):
    print('Running...')

class Flyable(object):
  def fly(self):
    print('Flying...')

对于需要Runnable功能的动物,就多继承一个Runnable,例如Dog:

class Dog(Mammal, Runnable):
  pass

对于需要Flyable功能的动物,就多继承一个Flyable,例如Bat:

class Bat(Mammal, Flyable):
  pass

通过多重继承,一个子类就可以同时获得多个父类的所有功能。
Mixin

在设计类的继承关系时,通常,主线都是单一继承下来的,例如,Ostrich继承自Bird。但是,如果需要“混入”额外的功能,通过多重继承就可以实现,比如,让Ostrich除了继承自Bird外,再同时继承Runnable。这种设计通常称之为Mixin。

为了更好地看出继承关系,我们把Runnable和Flyable改为RunnableMixin和FlyableMixin。类似的,你还可以定义出肉食动物CarnivorousMixin和植食动物HerbivoresMixin,让某个动物同时拥有好几个Mixin:

class Dog(Mammal, RunnableMixin, CarnivorousMixin):
  pass

Mixin的目的就是给一个类增加多个功能,这样,在设计类的时候,我们优先考虑通过多重继承来组合多个Mixin的功能,而不是设计多层次的复杂的继承关系。

Python自带的很多库也使用了Mixin。举个例子,Python自带了TCPServer和UDPServer这两类网络服务,而要同时服务多个用户就必须使用多进程或多线程模型,这两种模型由ForkingMixin和ThreadingMixin提供。通过组合,我们就可以创造出合适的服务来。

比如,编写一个多进程模式的TCP服务,定义如下:

class MyTCPServer(TCPServer, ForkingMixin):
  pass

编写一个多线程模式的UDP服务,定义如下:

class MyUDPServer(UDPServer, ThreadingMixin):
  pass

如果你打算搞一个更先进的协程模型,可以编写一个CoroutineMixin:

class MyTCPServer(TCPServer, CoroutineMixin):
  pass

这样一来,我们不需要复杂而庞大的继承链,只要选择组合不同的类的功能,就可以快速构造出所需的子类。
小结

由于Python允许使用多重继承,因此,Mixin就是一种常见的设计。

只允许单一继承的语言(如Java)不能使用Mixin的设计。

Python 相关文章推荐
python字符串连接的N种方式总结
Sep 17 Python
Python文件操作基本流程代码实例
Dec 11 Python
python随机在一张图像上截取任意大小图片的方法
Jan 24 Python
Python中使用遍历在列表中添加字典遇到的坑
Feb 27 Python
在Django的View中使用asyncio的方法
Jul 12 Python
django admin.py 外键,反向查询的实例
Jul 26 Python
python爬虫 urllib模块反爬虫机制UA详解
Aug 20 Python
python使用rsa非对称加密过程解析
Dec 28 Python
打包PyQt5应用时的注意事项
Feb 14 Python
Python decorator拦截器代码实例解析
Apr 04 Python
Python 操作 PostgreSQL 数据库示例【连接、增删改查等】
Apr 21 Python
Python 实现RSA加解密文本文件
Dec 30 Python
python输出当前目录下index.html文件路径的方法
Apr 28 #Python
Python实现基于权重的随机数2种方法
Apr 28 #Python
python使用urllib2实现发送带cookie的请求
Apr 28 #Python
python实现在windows下操作word的方法
Apr 28 #Python
介绍Python的@property装饰器的用法
Apr 28 #Python
Pyhthon中使用compileall模块编译源文件为pyc文件
Apr 28 #Python
在Python中使用__slots__方法的详细教程
Apr 28 #Python
You might like
php求正负数数组中连续元素最大值示例
2014/04/11 PHP
PHP实现加密的几种方式介绍
2015/02/22 PHP
PHP错误Warning:mysql_query()解决方法
2015/10/24 PHP
在WordPress中实现发送http请求的相关函数解析
2015/12/29 PHP
php实现计算百度地图坐标之间距离的方法
2016/05/05 PHP
php微信支付接口开发程序
2016/08/02 PHP
tp5(thinkPHP5框架)使用DB实现批量删除功能示例
2019/05/28 PHP
关于js拖拽上传 [一个拖拽上传修改头像的流程]
2011/07/13 Javascript
js中document.getElementByid、document.all和document.layers区分介绍
2011/12/08 Javascript
js控制输入框获得和失去焦点时状态显示的方法
2015/01/30 Javascript
认识Knockout及如何使用Knockout绑定上下文
2015/12/25 Javascript
jquery拖拽效果完整实例(附demo源码下载)
2016/01/14 Javascript
最简单纯JavaScript实现Tab标签页切换的方式(推荐)
2016/07/25 Javascript
javaScript语法总结
2016/11/25 Javascript
8 行 Node.js 代码实现代理服务器
2016/12/05 Javascript
微信小程序 tabs选项卡效果的实现
2017/01/05 Javascript
Angularjs2不同组件间的通信实例代码
2017/05/06 Javascript
深入理解Commonjs规范及Node模块实现
2017/05/17 Javascript
VUE实现表单元素双向绑定(总结)
2017/08/08 Javascript
angular1配合gulp和bower的使用教程
2018/01/19 Javascript
基于vue cli 通过命令行传参实现多环境配置
2018/07/12 Javascript
「中高级前端面试」JavaScript手写代码无敌秘籍(推荐)
2019/04/08 Javascript
JS面向对象编程基础篇(三) 继承操作实例详解
2020/03/03 Javascript
如何利用javascript接收json信息并进行处理
2020/08/06 Javascript
python脚本实现数据导出excel格式的简单方法(推荐)
2016/12/30 Python
django中的数据库迁移的实现
2020/03/16 Python
Python 如何操作 SQLite 数据库
2020/08/17 Python
浅析python连接数据库的重要事项
2021/02/22 Python
android面试问题与答案
2016/12/27 面试题
一封普通求职者的求职信
2013/11/20 职场文书
外企求职信范文分享
2013/12/31 职场文书
大专毕业生求职信
2014/07/05 职场文书
生物工程专业求职信
2014/09/03 职场文书
婚礼伴郎致辞
2015/07/28 职场文书
女方家长婚礼答谢词
2015/09/29 职场文书
创作书写之导游词实用技巧分享(干货)
2019/12/20 职场文书