详解duck typing鸭子类型程序设计与Python的实现示例


Posted in Python onJune 03, 2016

在程序设计中,鸭子类型(英语:duck typing)是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定。
这个概念的名字来源于由James Whitcomb Riley提出的鸭子测试,“鸭子测试”可以这样表述:
“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
在鸭子类型中,关注的不是对象的类型本身,而是它是如何使用的。例如,在不使用鸭子类型的语言中,我们可以编写一个函数,它接受一个类型为鸭的对象,并调用它的走和叫方法。在使用鸭子类型的语言中,这样的一个函数可以接受一个任意类型的对象,并调用它的走和叫方法。如果这些需要被调用的方法不存在,那么将引发一个运行时错误。任何拥有这样的正确的走和叫方法的对象都可被函数接受的这种行为引出了以上表述,这种决定类型的方式因此得名。
鸭子类型通常得益于不测试方法和函数中参数的类型,而是依赖文档、清晰的代码和测试来确保正确使用。从静态类型语言转向动态类型语言的用户通常试图添加一些静态的(在运行之前的)类型检查,从而影响了鸭子类型的益处和可伸缩性,并约束了语言的动态特性。

Python代码示例
上面这样说可能太空洞了。比如在Python中,有很多file-like的东西,比如StringIO,GzipFile,socket。它们有很多相同的方法,我们把它们当作文件使用。
又比如list.extend()方法中,我们并不关心它的参数是不是list,只要它是可迭代的,所以它的参数可以是list/tuple/dict/字符串/生成器等.
鸭子类型在动态语言中经常使用,非常灵活,使得python不想java那样专门去弄一大堆的设计模式。

下面例子用duck typing来实现多态。

#coding=utf-8 
class Duck: 
  def quack(self): 
    print "Quaaaaaack!" 
 
class Bird: 
  def quack(self): 
    print "bird imitate duck." 
 
class Doge: 
  def quack(self): 
    print "doge imitate duck." 
 
def in_the_forest(duck): 
  duck.quack() 
 
duck = Duck() 
bird = Bird() 
doge = Doge() 
for x in [duck, bird, doge]: 
  in_the_forest(x)

再举个栗子,
我们来hack输出流。

import sys 
 
sys.stdout = open('stdout.log', 'a') #只要是file-like,不管是什么类型 
print 'foo' 
 
sys.stdout = sys.__stdout__ #恢复 
print 'bar'

这样就把输出流给写入到文件中去了。

Python 相关文章推荐
Python用sndhdr模块识别音频格式详解
Jan 11 Python
解决python3 json数据包含中文的读写问题
May 10 Python
Appium+python自动化之连接模拟器并启动淘宝APP(超详解)
Jun 17 Python
python爬虫实现中英翻译词典
Jun 25 Python
Python程序打包工具py2exe和PyInstaller详解
Jun 28 Python
在Pycharm中调试Django项目程序的操作方法
Jul 17 Python
python调用Matplotlib绘制分布点图
Oct 18 Python
Numpy将二维数组添加到空数组的实现
Dec 05 Python
使用Python操作ArangoDB的方法步骤
Feb 02 Python
python numpy数组中的复制知识解析
Feb 03 Python
python 实现分组求和与分组累加求和代码
May 18 Python
python 图像增强算法实现详解
Jan 24 Python
详解字典树Trie结构及其Python代码实现
Jun 03 #Python
Python中利用Scipy包的SIFT方法进行图片识别的实例教程
Jun 03 #Python
Python中的descriptor描述器简明使用指南
Jun 02 #Python
Python黑魔法Descriptor描述符的实例解析
Jun 02 #Python
深入理解Python变量与常量
Jun 02 #Python
Python中的Descriptor描述符学习教程
Jun 02 #Python
从源码解析Python的Flask框架中request对象的用法
Jun 02 #Python
You might like
PHP编程中八种常见的文件操作方式
2006/11/19 PHP
按上下级层次关系输出内容的PHP代码
2010/07/17 PHP
php设置允许大文件上传示例代码
2014/03/10 PHP
php使用json_encode对变量json编码
2014/04/07 PHP
PHP易混淆函数的区别及用法汇总
2014/11/22 PHP
php异步:在php中使用fsockopen curl实现类似异步处理的功能方法
2016/12/10 PHP
Zend Framework路由器用法实例详解
2016/12/11 PHP
jQuery阻止事件冒泡具体实现
2013/10/11 Javascript
jQuery源码分析之jQuery.fn.each与jQuery.each用法
2015/01/23 Javascript
详细解读JavaScript编程中的Promise使用
2015/07/27 Javascript
JS实现样式清新的横排下拉菜单效果
2015/10/09 Javascript
内容滑动切换效果jquery.hwSlide.js插件封装
2016/07/07 Javascript
浅谈DOM的操作以及性能优化问题-重绘重排
2017/01/08 Javascript
Bootstrap入门教程一Hello Bootstrap初识
2017/03/02 Javascript
简单实现js鼠标跟随效果
2020/08/02 Javascript
简单实现jQuery轮播效果
2017/08/18 jQuery
ES6 迭代器(Iterator)和 for.of循环使用方法学习(总结)
2018/02/08 Javascript
详解Vue之父子组件传值
2019/04/01 Javascript
Vue 实现CLI 3.0 + momentjs + lodash打包时优化
2019/11/13 Javascript
vue中用 async/await 来处理异步操作
2020/07/18 Javascript
vue或react项目生产环境去掉console.log的操作
2020/09/02 Javascript
JavaScript事件概念详解(区分静态注册和动态注册)
2021/02/05 Javascript
vue使用echarts画组织结构图
2021/02/06 Vue.js
[40:29]2018DOTA2亚洲邀请赛 4.7总决赛 LGD vs Mineski 第一场
2018/04/10 DOTA
介绍Python的Django框架中的QuerySets
2015/04/20 Python
Python全局变量用法实例分析
2016/07/19 Python
Python随机生成均匀分布在三角形内或者任意多边形内的点
2017/12/14 Python
使用Windows批处理和WMI设置Python的环境变量方法
2019/08/14 Python
解决使用Pandas 读取超过65536行的Excel文件问题
2020/11/10 Python
H&M旗下高端女装品牌:& Other Stories
2018/05/07 全球购物
向国旗敬礼活动总结范文2014
2014/09/27 职场文书
天下第一关导游词
2015/02/06 职场文书
谁动了我的奶酪读书笔记
2015/06/30 职场文书
详解CSS开发过程中的20个快速提升技巧
2021/05/21 HTML / CSS
Redis分布式锁Redlock的实现
2021/08/07 Redis
如何在Python中妥善使用进度条详解
2022/04/05 Python