详解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实例分享:快速查找出被挂马的文件
Jun 08 Python
Python使用tablib生成excel文件的简单实现方法
Mar 16 Python
Python中创建字典的几种方法总结(推荐)
Apr 27 Python
python 全局变量的import机制介绍
Sep 07 Python
python 使用sys.stdin和fileinput读入标准输入的方法
Oct 17 Python
flask框架单元测试原理与用法实例分析
Jul 23 Python
Django如何简单快速实现PUT、DELETE方法
Jul 24 Python
PyTorch的Optimizer训练工具的实现
Aug 18 Python
Python高级编程之继承问题详解(super与mro)
Nov 19 Python
tensorflow模型的save与restore,及checkpoint中读取变量方式
May 26 Python
详解Python中import机制
Sep 11 Python
Python中过滤字符串列表的方法
Dec 22 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
DEDECMS首页调用图片集里的多张图片
2015/06/05 PHP
weiphp微信公众平台授权设置
2016/01/04 PHP
php原生导出excel文件的两种方法(推荐)
2016/11/19 PHP
Zend Framework入门教程之Zend_Registry组件用法详解
2016/12/09 PHP
PHP中include()与require()的区别说明
2017/02/14 PHP
浅谈thinkphp的nginx配置,以及重写隐藏index.php入口文件方法
2019/10/12 PHP
Laravel开启跨域请求的方法
2019/10/13 PHP
PHP获取类私有属性的3种方法
2020/09/10 PHP
使用TextRange获取输入框中光标的位
2006/10/14 Javascript
简单的无缝滚动程序-仅几行代码
2007/05/08 Javascript
jQuery右键菜单contextMenu使用实例
2011/09/28 Javascript
jquery实现图片灯箱明暗的遮罩效果
2013/11/15 Javascript
jquery获取复选框被选中的值
2014/04/10 Javascript
JQuery Tips相关(1)----关于$.Ready()
2014/08/14 Javascript
JavaScript strike方法入门实例(给字符串加上删除线)
2014/10/17 Javascript
jQuery实时显示鼠标指针位置和键盘ASCII码
2016/03/28 Javascript
Bootstrap的class样式小结
2016/12/01 Javascript
微信小程序动态添加分享数据
2017/06/14 Javascript
jQuery Ajax实现Select多级关联动态绑定数据的实例代码
2018/10/26 jQuery
vue 父组件给子组件传值子组件给父组件传值的实例代码
2019/04/15 Javascript
JQuery实现简单的复选框树形结构图示例【附源码下载】
2019/07/16 jQuery
python fabric实现远程部署
2017/01/05 Python
Python实现对象转换为xml的方法示例
2017/06/08 Python
python difflib模块示例讲解
2017/09/13 Python
selenium + python 获取table数据的示例讲解
2018/10/13 Python
Python面向对象之类的内置attr属性示例
2018/12/14 Python
python 实现"神经衰弱"翻牌游戏
2020/11/09 Python
HTML5 语音搜索只需一句代码
2013/01/03 HTML / CSS
次世代生活态度:Hypebeast
2018/07/05 全球购物
凯普林包包西班牙官网:Kipling西班牙
2019/04/12 全球购物
校园文化艺术节宣传标语
2014/10/09 职场文书
开天辟地观后感
2015/06/09 职场文书
我的法兰西岁月观后感
2015/06/09 职场文书
总经理年会致辞
2015/07/29 职场文书
写作之关于描写老人的好段摘抄
2019/11/14 职场文书
cypress测试本地web应用
2022/06/01 Javascript