浅析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中文字符串截取问题
Jun 15 Python
Python使用QQ邮箱发送Email的方法实例
Feb 09 Python
Python编程修改MP3文件名称的方法
Apr 19 Python
python实现装饰器、描述符
Feb 28 Python
python smtplib模块自动收发邮件功能(二)
May 22 Python
对Python实现简单的API接口实例讲解
Dec 10 Python
Python微医挂号网医生数据抓取
Jan 24 Python
查看python安装路径及pip安装的包列表及路径
Apr 03 Python
Python 抓取数据存储到Redis中的操作
Jul 16 Python
Python import模块的缓存问题解决方案
Jun 02 Python
Python制作动态字符画的源码
Aug 04 Python
Python获取字典中某个key的value
Apr 13 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
真正面向对象编程:PHP5.01发布
2006/10/09 PHP
杏林同学录(三)
2006/10/09 PHP
使用php判断网页是否gzip压缩
2013/06/25 PHP
php的数组与字符串的转换函数整理汇总
2013/07/18 PHP
PHP中多维数组的foreach遍历示例
2014/06/13 PHP
php微信公众号开发(2)百度BAE搭建和数据库使用
2016/12/15 PHP
Laravel中Facade的加载过程与原理详解
2017/09/22 PHP
PHP PDOStatement::execute讲解
2019/01/31 PHP
PHPExcel实现的读取多工作表操作示例
2020/04/14 PHP
从JQuery源码分析JavaScript函数的apply方法与call方法
2014/09/25 Javascript
使用Sticker.js实现贴纸效果
2015/01/28 Javascript
浅谈javascript中this在事件中的应用
2015/02/15 Javascript
JSON相关知识汇总
2015/07/03 Javascript
JavaScript实现256色转灰度图
2017/02/22 Javascript
Angular.js实现动态加载组件详解
2017/05/28 Javascript
nodejs express配置自签名https服务器的方法
2018/05/22 NodeJs
使用mpvue搭建一个初始小程序及项目配置方法
2018/12/03 Javascript
微信小程序实现蒙版弹出窗功能
2019/09/17 Javascript
Python 第一步 hello world
2009/09/25 Python
使用Python编写爬虫的基本模块及框架使用指南
2016/01/20 Python
Python3 Tkinkter + SQLite实现登录和注册界面
2019/11/19 Python
解决Tensorflow 内存泄露问题
2020/02/05 Python
HTML5中实现拖放效果无须借助javascript
2012/12/26 HTML / CSS
利用HTML5绘制点线面组成的3D图形的示例
2015/05/12 HTML / CSS
三星新西兰官网:Samsung新西兰
2019/03/05 全球购物
学前教育毕业生自荐信
2013/10/29 职场文书
厉行勤俭节约倡议书
2014/05/16 职场文书
财务部会计岗位职责
2015/02/03 职场文书
2015年小学开学寄语
2015/02/27 职场文书
2015年保安个人工作总结
2015/04/02 职场文书
2015年教学副校长工作总结
2015/07/22 职场文书
关爱空巢老人感想
2015/08/11 职场文书
小学生作文写作技巧100例,非常实用!
2019/07/08 职场文书
浅谈MySQL 亿级数据分页的优化
2021/06/15 MySQL
python之PySide2安装使用及QT Designer UI设计案例教程
2021/07/26 Python
Nginx 502 bad gateway错误解决的九种方案及原因
2022/08/14 Servers