浅析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常用正则表达式符号浅析
Aug 13 Python
使用Python脚本将Bing的每日图片作为桌面的教程
May 04 Python
Python极简代码实现杨辉三角示例代码
Nov 15 Python
python爬虫的工作原理
Mar 05 Python
快速入门python学习笔记
Dec 06 Python
Python使用Scrapy保存控制台信息到文本解析
Dec 27 Python
对python中矩阵相加函数sum()的使用详解
Jan 28 Python
用Python解决x的n次方问题
Feb 08 Python
Python和Go语言的区别总结
Feb 20 Python
Windows下实现将Pascal VOC转化为TFRecords
Feb 17 Python
图解Python中深浅copy(通俗易懂)
Sep 03 Python
Python集合set()使用的方法详解
Mar 18 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+DBM的同学录程序(3)
2006/10/09 PHP
PHP utf-8编码问题,utf8编码,数据库乱码,页面显示输出乱码
2013/04/08 PHP
PhpDocumentor 2安装以及生成API文档的方法
2014/05/21 PHP
typecho插件编写教程(五):核心代码
2015/05/28 PHP
ThinkPHP5.0 图片上传生成缩略图实例代码说明
2018/06/20 PHP
Laravel框架运行出错提示RuntimeException No application encryption key has been specified.解决方法
2019/04/02 PHP
php菜单/评论数据递归分级算法的实现方法
2019/08/01 PHP
laravel 自定义常量的两种方案
2019/10/14 PHP
Javascript中eval函数的使用方法与示例
2007/04/09 Javascript
jQuery-ui中自动完成实现方法
2010/06/10 Javascript
关于juqery radio写法的兼容性问题(新老版本jquery)
2010/06/14 Javascript
浅谈利用JavaScript进行的DDoS攻击原理与防御
2015/06/04 Javascript
jquery实现带渐变淡入淡出并向右依次展开的多级菜单效果实例
2015/08/22 Javascript
JavaScript浏览器对象之一Window对象详解
2016/06/03 Javascript
html+javascript+bootstrap实现层级多选框全层全选和多选功能
2017/03/09 Javascript
JS基于正则实现数字千分位用逗号分隔的方法
2017/06/16 Javascript
在vscode里使用.vue代码模板的方法
2018/04/28 Javascript
vue添加axios,并且指定baseurl的方法
2018/09/19 Javascript
详解Vue组件插槽的使用以及调用组件内的方法
2018/11/13 Javascript
详解vue-cli+element-ui树形表格(多级表格折腾小计)
2019/04/17 Javascript
Python读写Excel文件方法介绍
2014/11/22 Python
Python  pip安装lxml出错的问题解决办法
2017/02/10 Python
Python+OpenCV图片局部区域像素值处理改进版详解
2019/01/23 Python
为什么说Python可以实现所有的算法
2019/10/04 Python
解决tensorflow添加ptb库的问题
2020/02/10 Python
python selenium操作cookie的实现
2020/03/18 Python
CSS3制作Dropdown下拉菜单的方法
2015/07/18 HTML / CSS
Nike英国官网:Nike.com (UK)
2017/02/13 全球购物
CheapTickets泰国:廉价航班,查看促销价格并预订机票
2019/12/28 全球购物
会计实习期自我鉴定
2013/10/06 职场文书
班风口号
2014/06/18 职场文书
学术会议邀请函
2015/01/30 职场文书
团结主题班会
2015/08/13 职场文书
幼儿园托班开学寄语(2016秋季)
2015/12/03 职场文书
优质服务标语口号
2015/12/26 职场文书
小学四年级班务总结该怎么写?
2019/08/16 职场文书