浅析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 生成目录树及显示文件大小的代码
Jul 23 Python
python Django连接MySQL数据库做增删改查
Nov 07 Python
python解决pandas处理缺失值为空字符串的问题
Apr 08 Python
python2与python3的print及字符串格式化小结
Nov 30 Python
kali中python版本的切换方法
Jul 11 Python
获取Pytorch中间某一层权重或者特征的例子
Aug 17 Python
利用Python复制文件的9种方法总结
Sep 02 Python
自适应线性神经网络Adaline的python实现详解
Sep 30 Python
python实现身份证实名认证的方法实例
Nov 08 Python
基于python实现百度语音识别和图灵对话
Nov 02 Python
python使用Windows的wmic命令监控文件运行状况,如有异常发送邮件报警
Jan 30 Python
详解Python内置模块Collections
Mar 22 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安装攻略:常见问题解答(二)
2006/10/09 PHP
分享PHP入门的学习方法
2007/01/02 PHP
php实现通过soap调用.Net的WebService asmx文件
2017/02/27 PHP
Laravel5.1 框架控制器基础用法实例分析
2020/01/04 PHP
javascript 学习之旅 (2)
2009/02/05 Javascript
Js中setTimeout()和setInterval() 何时被调用执行的用法
2013/04/12 Javascript
解析JavaScript中的不可见数据类型
2013/12/02 Javascript
jQuery中:eq()选择器用法实例
2014/12/29 Javascript
jQuery使用hide方法隐藏页面上指定元素的方法
2015/03/30 Javascript
jquery中$each()方法的使用指南
2015/04/30 Javascript
原生JavaScript实现异步多文件上传
2015/12/02 Javascript
JavaScript代码里的判断小结
2016/08/22 Javascript
AngularJS实现数据列表的增加、删除和上移下移等功能实例
2016/09/05 Javascript
node.js连接MongoDB数据库的2种方法教程
2017/05/17 Javascript
JS计算输出100元钱买100只鸡问题的解决方法
2018/01/04 Javascript
通过一次报错详细谈谈Point事件
2018/05/17 Javascript
vue学习笔记之slot插槽用法实例分析
2020/02/29 Javascript
JavaScript随机数的组合问题案例分析
2020/05/16 Javascript
jQuery HTML设置内容和属性操作实例分析
2020/05/20 jQuery
js实现点击烟花特效
2020/10/14 Javascript
Tornado服务器中绑定域名、虚拟主机的方法
2014/08/22 Python
python直接访问私有属性的简单方法
2016/07/25 Python
python中dict字典的查询键值对 遍历 排序 创建 访问 更新 删除基础操作方法
2018/09/13 Python
在Python 中实现图片加框和加字的方法
2019/01/26 Python
pandas的相关系数与协方差实例
2019/12/27 Python
python由已知数组快速生成新数组的方法
2020/04/08 Python
python库skimage给灰度图像染色的方法示例
2020/04/27 Python
Python使用windows设置定时执行脚本
2020/11/12 Python
使用HTML5技术开发一个属于自己的超酷颜色选择器
2013/09/22 HTML / CSS
护理专业的自荐信
2013/10/22 职场文书
鞋类设计与工艺专业销售求职信
2013/11/01 职场文书
语文教学随笔感言
2014/02/18 职场文书
公司市场部岗位职责
2015/04/15 职场文书
php微信小程序解包过程实例详解
2021/03/31 PHP
Python中的xlrd模块使用整理
2021/06/15 Python
Python中itertools库的四个函数介绍
2022/04/06 Python