浅析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入门之modf()方法的使用
May 15 Python
深入理解python对json的操作总结
Jan 05 Python
Python中文件I/O高效操作处理的技巧分享
Feb 04 Python
Python3.6通过自带的urllib通过get或post方法请求url的实例
May 10 Python
Python3匿名函数用法示例
Jul 25 Python
Python 变量的创建过程详解
Sep 02 Python
pytorch 实现将自己的图片数据处理成可以训练的图片类型
Jan 08 Python
python+Selenium自动化测试——输入,点击操作
Mar 06 Python
python中return如何写
Jun 18 Python
用Python制作灯光秀短视频的思路详解
Apr 13 Python
Python编解码问题及文本文件处理方法详解
Jun 20 Python
Python 数据科学 Matplotlib图库详解
Jul 07 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/01/02 PHP
php查询mysql大量数据造成内存不足的解决方法
2015/03/04 PHP
PHP SOCKET编程详解
2015/05/22 PHP
laravel5.6中的外键约束示例
2019/10/23 PHP
PHP架构及原理知识点详解
2019/12/22 PHP
百度 popup.js 完美修正版非常的不错 脚本之家推荐
2009/04/17 Javascript
IE6图片加载的一个BUG解决方法
2010/07/13 Javascript
AeroWindow 基于JQuery的弹出窗口插件
2011/06/27 Javascript
js实现动态添加、删除行、onkeyup表格求和示例
2013/08/18 Javascript
详解JavaScript中的表单验证
2015/06/16 Javascript
JavaScript中数据结构与算法(五):经典KMP算法
2015/06/19 Javascript
浅谈JavaScript的全局变量与局部变量
2016/06/10 Javascript
浅谈jQuery添加的HTML,JS失效的问题
2016/10/05 Javascript
微信小程序 安全包括(框架、功能模块、账户使用)详解
2017/01/16 Javascript
详解用vue-cli来搭建vue项目和webpack
2017/04/20 Javascript
利用JS如何计算字符串所占字节数示例代码
2017/09/13 Javascript
React Native 通告消息竖向轮播组件的封装
2020/08/25 Javascript
vue代理和跨域问题的解决
2018/07/18 Javascript
微信公众号平台接口开发 获取access_token过程解析
2019/08/14 Javascript
JS中队列和双端队列实现及应用详解
2020/09/29 Javascript
Python 查找list中的某个元素的所有的下标方法
2018/06/27 Python
python  ceiling divide 除法向上取整(或小数向上取整)的实例
2019/12/27 Python
Django 多对多字段的更新和插入数据实例
2020/03/31 Python
TensorFlow固化模型的实现操作
2020/05/26 Python
Visual Studio code 配置Python开发环境
2020/09/11 Python
CSS3中引入多种自定义字体font-face
2020/06/12 HTML / CSS
详解HTML5 data-* 自定义属性
2018/01/24 HTML / CSS
实现向右循环移位
2014/07/31 面试题
最新的咖啡店创业计划书
2013/12/30 职场文书
学习张丽丽心得体会
2014/09/03 职场文书
校园广播稿精选
2014/10/01 职场文书
2014年基层党建工作总结
2014/11/11 职场文书
邀请函怎么写
2015/01/30 职场文书
测量员岗位职责
2015/02/14 职场文书
2015年档案管理员工作总结
2015/05/13 职场文书
一文搞懂Python Sklearn库使用
2021/08/23 Python