详解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的框架中一些会话程序的管理
Apr 20 Python
Python控制多进程与多线程并发数总结
Oct 26 Python
python如何统计序列中元素
Jul 31 Python
Python 查找字符在字符串中的位置实例
May 02 Python
使用python生成杨辉三角形的示例代码
Aug 29 Python
Python实战购物车项目的实现参考
Feb 20 Python
Django 对IP访问频率进行限制的例子
Aug 30 Python
Python从列表推导到zip()函数的5种技巧总结
Oct 23 Python
使用Python实现 学生学籍管理系统
Nov 26 Python
常用python爬虫库介绍与简要说明
Jan 25 Python
python 回溯法模板详解
Feb 26 Python
python各种excel写入方式的速度对比
Nov 10 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
给apache2.2加上mod_encoding模块後 php5.2.0 处理url出现bug
2007/04/12 PHP
php之对抗Web扫描器的脚本技巧
2008/10/01 PHP
php标签云的实现代码
2012/10/10 PHP
php在数据库抽象层简单使用PDO的方法
2015/11/03 PHP
php通过文件头判断格式的方法
2016/05/28 PHP
微信公众号实现会员卡领取功能
2017/06/08 PHP
PHP call_user_func和call_user_func_array函数的简单理解与应用分析
2019/11/25 PHP
jquery创建一个新的节点对象(自定义结构/内容)的好方法
2013/01/21 Javascript
js克隆对象、数组的常用方法介绍
2013/09/26 Javascript
JavaScript统计字符串中每个字符出现次数完整实例
2016/01/28 Javascript
原生js验证简洁注册登录页面
2016/12/17 Javascript
javascript修改浏览器title方法 JS动态修改浏览器标题
2017/11/30 Javascript
js点击时关闭该范围下拉菜单之外的菜单方法
2018/01/11 Javascript
详解封装基础的angular4的request请求方法
2018/06/05 Javascript
Vuex的actions属性的具体使用
2019/04/14 Javascript
mpvue性能优化实战技巧(小结)
2019/04/17 Javascript
如何根据业务封装自己的功能组件
2019/04/19 Javascript
vue滚动固定顶部及修改样式的实例代码
2019/05/30 Javascript
关于layui的动态图标不显示的解决方法
2019/09/04 Javascript
javascript设计模式 ? 原型模式原理与应用实例分析
2020/04/10 Javascript
python获得linux下所有挂载点(mount points)的方法
2015/04/29 Python
Python + selenium + requests实现12306全自动抢票及验证码破解加自动点击功能
2018/11/23 Python
Python对列表的操作知识点详解
2019/08/20 Python
python3中关于excel追加写入格式被覆盖问题(实例代码)
2020/01/10 Python
Python3查找列表中重复元素的个数的3种方法详解
2020/02/13 Python
Python+PyQt5实现灭霸响指功能
2020/05/25 Python
python如何处理程序无法打开
2020/06/16 Python
Python创建简单的神经网络实例讲解
2021/01/04 Python
Html5 postMessage实现跨域消息传递
2016/03/11 HTML / CSS
法国面料和小百货在线商店:Mondial Tissus
2019/03/23 全球购物
Carrs Silver官网:英国著名的银器品牌
2020/08/29 全球购物
体育学院毕业生自荐信
2013/11/03 职场文书
竞争上岗实施方案
2014/03/21 职场文书
Axios代理配置及封装响应拦截处理方式
2022/04/07 Vue.js
从原生JavaScript到React深入理解
2022/07/23 Javascript
JavaScript实现简单的音乐播放器
2022/08/14 Javascript