Python学习笔记之Python的多重继承和MixIn
多重继承
继承是面向对象编程的一个重要的方式,因为通过继承,子类就可以扩展父类的功能。
回忆一下Animal
类层次的设计,假设我们要实现以下4种动物:
- Dog - 狗狗;
- Bat - 蝙蝠;
- Parrot - 鹦鹉;
- Ostrich - 鸵鸟。
如果按照哺乳动物和鸟类归类,我们可以设计出这样的类的层次:
但是如果按照“能跑”和“能飞”来归类,我们就应该设计出这样的类的层次:
如果要把上面的两种分类都包含进来,我们就得设计更多的层次:
- 哺乳类:能跑的哺乳类,能飞的哺乳类;
- 鸟类:能跑的鸟类,能飞的鸟类。
这么一来,类的层次就复杂了:
如果要再增加“宠物类”和“非宠物类”,这么搞下去,类的数量会呈指数增长,很明显这样设计是不行的。
正确的做法是采用多重继承。首先,主要的类层次仍按照哺乳类和鸟类设计:
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的设计。
为了解决多重继承的问题,Java引入了接口 (interface)技术,Lisp、Ruby引入了 Mix-in 技术。
参考
Python学习笔记之Python的多重继承和MixIn的更多相关文章
- python 学习笔记 9 -- Python强大的自省简析
1. 什么是自省? 自省就是自我评价.自我反省.自我批评.自我调控和自我教育,是孔子提出的一种自我道德修养的方法.他说:“见贤思齐焉,见不贤而内自省也.”(<论语·里仁>)当然,我们今天不 ...
- python 学习笔记一——Python安装和IDLE使用
好吧,一直准备学点啥,前些日子也下好了一些python电子书,但之后又没影了.年龄大了,就是不爱学习了.那就现在开始吧. 安装python 3 Mac OS X会预装python 2,Linux的大多 ...
- python学习笔记(一):python简介和入门
最近重新开始学习python,之前也自学过一段时间python,对python还算有点了解,本次重新认识python,也算当写一个小小的教程.一.什么是python?python是一种面向对象.解释型 ...
- python学习笔记(python简史)
一.python介绍 python的创始人为吉多·范罗苏姆(Guido van Rossum) 目前python主要应用领域: ·云计算 ·WEB开发 ·科学运算.人工智能 ·系统运维 ·金融:量化交 ...
- python学习笔记(1)--python特点
python诞生于复杂的信息系统时代,是计算机时代演进的一种选择. python的特点,通用语言,脚本语言,跨平台语言.这门语言可以用于普适的计算,不局限于某一类应用,通用性是它的最大特点.pytho ...
- python学习笔记之——python模块
1.python模块 Python 模块(Module),是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义和Python语句. 模块让你能够有逻辑地组织你的 Python ...
- Python学习笔记 - day12 - Python操作NoSQL
NoSQL(非关系型数据库) NoSQL,指的是非关系型的数据库.NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称.用于超大规模数据的存储.(例如 ...
- [Python学习笔记1]Python语言基础 数学运算符 字符串 列表
这个系列是我在学习Python语言的过程中记录的笔记,主要是一些知识点汇总,而非学习教程,可供有一定编程基础者参考.文中偏见和不足难以避免,仅供参考,欢迎批评指正. 本系列笔记主要参考文献是官网文档: ...
- python学习笔记一 python入门(基础篇)
简单介绍一下python2.x和3.5的区别 print 在python3.5中print 变为print() Old: print * New: print( * ) 如果想要不换行,之前的 ...
随机推荐
- 【黑金原创教程】【Modelsim】【第一章】Modelsim仿真的扫盲文
声明:本文为黑金动力社区(http://www.heijin.org)原创教程,如需转载请注明出处,谢谢! 黑金动力社区2013年原创教程连载计划: http://www.cnblogs.com/al ...
- 【BZOJ3585/3339】mex 莫队算法+分块
[BZOJ3585]mex Description 有一个长度为n的数组{a1,a2,...,an}.m次询问,每次询问一个区间内最小没有出现过的自然数. Input 第一行n,m. 第二行为n个数. ...
- LVS负载均衡服务
LVS负载均衡服务 LVS负载均衡调度技术是在Linux内核中实现的,因此被称为Linux虚拟服务器.使用LVS时,不能直接配置内核中的ipvs,而需要使用ipvs的管理工具ipvsadm进行管理. ...
- [Domino]执行命令load design的时候出现Warning: Cannot locate design template
发现问题 在做Pseudo Test的时候被QA测出了一个问题.在Domino concole打命令“load design”,被Workbench翻译过后的数据库提示了一个警告:Warning: C ...
- LeetCode 笔记系列16.3 Minimum Window Substring [从O(N*M), O(NlogM)到O(N),人生就是一场不停的战斗]
题目:Given a string S and a string T, find the minimum window in S which will contain all the characte ...
- Go语言 基本类型
在内存中的形式 首先看一下在go中,一些基础类型在内存中是以什么形态存在的,如下图所示: 变量j的类型是int32, 而变量i的类型是int,两者不是同一个类型,所以赋值操作i=j是一种类型错误can ...
- append和innerHTML的区别以及使用方法
1.append jquery中的append的使用方式:$("#id").append("<a href='#'>test</a>") ...
- luarocks安装以及lfs安装
一.先安装lua: brew install lua 我本机的安装路径为:/usr/local/Cellar/lua/5.3.4_2 二.安装luarocks 下载luarocks的安装包: http ...
- IPython的基本功能(转)
原文:http://kochiya.me/www/posts/Ipython!.html 前几天偶然在公司内网上拖了一本 Learning IPython for Interactive Comput ...
- python常见模块之os模块
os模块是python系统与操作系统交互的一个接口 os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 os.chdir("dirname") 改变当前 ...