浅析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 相关文章推荐
如何搜索查找并解决Django相关的问题
Jun 30 Python
Python中的异常处理学习笔记
Jan 28 Python
python使用super()出现错误解决办法
Aug 14 Python
Python面向对象类继承和组合实例分析
May 28 Python
Python实现基于SVM的分类器的方法
Jul 19 Python
Windows下PyCharm2018.3.2 安装教程(图文详解)
Oct 24 Python
Python爬取爱奇艺电影信息代码实例
Nov 26 Python
tensorflow之并行读入数据详解
Feb 05 Python
python计算导数并绘图的实例
Feb 29 Python
Pytorch通过保存为ONNX模型转TensorRT5的实现
May 25 Python
关于python3.9安装wordcloud出错的问题及解决办法
Nov 02 Python
Python中threading库实现线程锁与释放锁
May 17 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 文件扩展名 获取函数
2009/06/03 PHP
十幅图告诉你什么是PHP引用
2015/02/22 PHP
PHP实现获取某个月份周次信息的方法
2015/08/11 PHP
php中的抽象方法和抽象类
2017/02/14 PHP
javascript attachEvent和addEventListener使用方法
2009/03/19 Javascript
stream.js 一个很小、完全独立的Javascript类库
2011/10/28 Javascript
原生Js页面滚动延迟加载图片实现原理及过程
2013/06/24 Javascript
getAsDataURL在Firefox7.0下无法预览本地图片的解决方法
2013/11/15 Javascript
详解Bootstrap插件
2016/04/25 Javascript
JavaScript中setter和getter方法介绍
2016/07/11 Javascript
node.js文件上传处理示例
2016/10/27 Javascript
利用Angular.js编写公共提示模块的方法教程
2017/05/28 Javascript
Angular限制input框输入金额(是小数的话只保留两位小数点)
2017/07/13 Javascript
JS动态修改网页body的背景色实例代码
2017/10/07 Javascript
原生js实现自定义消息提示框
2020/11/19 Javascript
利用Python实现简单的相似图片搜索的教程
2015/04/23 Python
python绘制铅球的运行轨迹代码分享
2017/11/14 Python
pytorch使用指定GPU训练的实例
2019/08/19 Python
下载与当前Chrome对应的chromedriver.exe(用于python+selenium)
2020/01/14 Python
有关Tensorflow梯度下降常用的优化方法分享
2020/02/04 Python
python3用urllib抓取贴吧邮箱和QQ实例
2020/03/10 Python
Python greenlet和gevent使用代码示例解析
2020/04/01 Python
TensorFlow的reshape操作 tf.reshape的实现
2020/04/19 Python
python实现企业微信定时发送文本消息的实例代码
2020/11/25 Python
python基于pexpect库自动获取日志信息
2021/02/01 Python
美国奢侈品购物平台:Orchard Mile
2018/05/02 全球购物
Bibloo匈牙利:女装、男装、童装及鞋子和配饰
2019/04/14 全球购物
Abbott Lyon官网:女士手表、珠宝及配件
2020/12/26 全球购物
空字符串(“”)和null的区别
2012/11/13 面试题
测绘专业大学生职业生涯规划书
2014/02/10 职场文书
信息专业学生学习的自我评价
2014/02/17 职场文书
机械系毕业生求职信
2014/05/28 职场文书
物流专业求职信
2014/06/30 职场文书
给客户的感谢信
2015/01/21 职场文书
医生辞职信范文
2015/03/02 职场文书
springboot用户数据修改的详细实现
2022/04/06 Java/Android