目录

一、来源

二、说明

三、举例

四、不足


一、来源

在程序设计中,鸭子类型 (duck typing) 是动态类型的一种风格。在此风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定的。

事实上,duck typing 的概念源于一个米国诗人的诗句:

" When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck."

—— James Whitcomb Riley

当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”

—— 詹姆斯·惠特科姆·莱利

后来,工程师在 Python 中引入了上述 duck typing 的语言推断测试规则。换言之,它不关注对象的类型,而是关注对象具有的行为 (方法)。以下是 Python 术语表对其定义的阐述:

Pythonic programming style that determines an object's type by inspection of its method or attribute signature rather than by explicit relationship to some type object ("If it looks like a duck and quacks like a duck, it must be a duck.") By emphasizing interfaces rather than specific types, well-designed code improves its flexibility by allowing polymorphic substitution. Duck-typing avoids tests using type() or isinstance(). Instead, it typically employs the EAFP (Easier to Ask Forgiveness than Permission) style of programming.


二、说明

鸭子类型 (duck typing) 作为程序设计中的一种 类型推断风格,适用于 大部分脚本语言 / 动态语言 (如 Python、Ruby、Perl、Julia、JavaScript 等) 和 某些静态语言 (如 Golang,通常静态类型语言在编译前便已显式指定变量类型,而 Golang 却则在编译时推断变量类型)。支持 duck typing 的语言,其 解释器/编译器 将会在解释/解析 (Parse) 或编译时推断对象类型。

鸭子测试 可以表述为:“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子”。在 duck typing 中,关注的不是对象的类型本身,而是它是如何使用的。与此同时,与 duck typing 相对应的风格是 normal typing,后者由对象类型决定了对象的特性。以下对比说明二者区别:

一方面,以 形象化的表述 为例:在使用 normal typing 的语言中,可以编写一个 “鸭子动作” 函数,它能够接受一个类型为 “鸭子” 的对象,并调用它的 “飞”、“跑” 等方法。在运行前,需要进行对象是否确实为 “鸭子” 等类型检查。相应地,在使用 duck typing 的语言中,也可以编写一个 “鸭子动作” 函数,它能够接受一个任意类型的对象,并调用它的 “飞”、“跑” 等方法。换言之,只要传入对象具有正确的 “飞”、“跑” 等方法,就都可以被函数正常接受和调用。但若这些需要被调用的方法不存在,那么将引发一个运行时错误。

另一方面,以 结合语言的表述 为例:C 属于 normal typing,在 编译阶段进行静态检查,函数定义和传参类型不一致就报错。相应地,Python 属于 duck typing,对象的类型不重要,只要对象具有类型 duck 的方法和属性,那么它就会被当做类型 duck 来使用 (因此经常能够混用类型)。Python 没有静态检查类型匹配情况,只有 运行时找不到相应属性和方法时才报错

此外,如果只了解 Java、C++ 等静态语言,可能对鸭子类型的理解并不深刻,因为静态语言中,对象的特性取决于其父类。而动态语言则显著有别,例如 Python 的迭代器 (iterator),任何支持迭代协议 (同时实现 __iter__ 和 __next__ 方法) 的对象都可称之为迭代器,但对象本身是什么类型并不受到限制,甚至可以为任何自定义类。


三、举例

>>> class Duck:"Duck 对象具有 fly 方法 (鸭子的飞行行为) 和 run 方法 (鸭子的奔跑行为)"def fly(self):print("Duck flying")def run(self):print("Duck running")>>> class Chick:"Chick 对象具有 fly 方法 (小鸡的飞行行为) 和 run 方法 (小鸡的奔跑行为)"def fly(self):print("Chick flying")def run(self):print("Chick running")>>> class Plane:"Plane 对象具有 fly 方法 (飞机的飞行行为)" def fly(self):print("Plane flying")>>> class Fish:"Fish 对象具有 swim 方法 (鱼儿的游泳行为)"def swim(self):print("FIsh Swimming")>>> def go(entity):    "令传入实例对象 entity 执行飞行和奔跑操作 (不论什么东西能飞、能跑就行)"entity.fly()  # 令传入实例对象 entity 执行 fly 方法entity.run()  # 令传入实例对象 entity 执行 run 方法>>> duck = Duck()  # 实例化 Duck 对象
>>> chick = Chick()  # 实例化 Chick 对象
>>> plane = Plane()  # 实例化 Plane 对象
>>> fish = Fish()  # 实例化 Fish 对象>>> go(duck)  # 有 fly 和 run 方法就能正常运行, 不关心实例对象的类型是什么 (不论什么东西, 能飞和跑就行)
Duck flying
Duck running>>> go(chick)  # 有 fly 和 run 方法就能正常运行, 不关心实例对象的类型是什么 (不论什么东西, 能飞和跑就行)
Chick flying
Chick running>>> go(plane)  # 没有 run 方法就报错, 不关心实例对象的类型是什么 (不论什么东西, 不能跑就不行)
Plane flying
Traceback (most recent call last):File "<pyshell#20>", line 1, in <module>go(plane)File "<pyshell#13>", line 3, in goentity.run()
AttributeError: 'Plane' object has no attribute 'run'>>> go(fish)  # 没有 fly 方法就报错, 不关心实例对象的类型是什么 (不论什么东西, 不能飞就不行)
Traceback (most recent call last):File "<pyshell#44>", line 1, in <module>go(fish)File "<pyshell#35>", line 2, in goentity.fly()
AttributeError: 'Fish' object has no attribute 'fly'

至于各种编程语言中的 duck typing,还可以看这其中的例子:编程语言中的 DUCK TYPING


四、不足

鸭子类型 (duck typing) 没有任何静态检查 (如类型检查、属性检查、方法签名检查等),其通常得益于 不测试方法和函数中参数的类型,而是 依赖文档、清晰的代码和测试来确保正确使用。这既是优点也是缺点,缺点是需要通过文档才能知道参数类型,为了弥补这方面的不足,Python3.6 引入了类型信息,定义变量的时候可以指定类型。此外,从静态类型语言转向动态类型语言的用户通常试图添加一些静态的 (运行前的) 类型检查,从而影响了鸭子类型的益处和可伸缩性,并约束了语言的动态特性。

鸭子类型 (duck typing) 语言的程序 可能会在运行时因不具备某种特定的方法而抛出异常 (例如上例中的 plane 没有 run 方法、fish 没有 fly 方法),形象化地举例说明:如果一只小狗 (对象) 想加入合唱团 (以对象会不会嘎嘎嘎叫的方法为检验标准),也学鸭子那么嘎嘎嘎叫,好吧,它加入了,可是加入之后,却不会像鸭子那样走路,那么,迟早要出问题的。

再举个例子:一只小老鼠被猫盯上了,情急之下,它学了狗叫,猫撤了之后,小老鼠的妈妈不无感叹的对它说:看吧,我让你学的这门儿外语多么重要啊。这虽然是个段子,但是,由于猫在思考时,使用了 "鸭子测试",它以为会叫的就是狗,会对自己产生威胁,所以撤退了,也正是因为这个错误的判断,它误失了一次进食机会。


参考文献

duck type - 简书

Python:动态语言与鸭子类型

编程语言中的 DUCK TYPING - SegmentFault 思否

duck type鸭子类型 - youxin - 博客园

到底啥是鸭子类型(duck typing)带简单例子 - 筱筱的春天 - 博客园

https://baike.baidu.com/item/鸭子类型/10845665?fr=aladdin

【Python】浅谈 鸭子类型 (Duck Typing)相关推荐

  1. Python编程基础:第四十九节 鸭子类型Duck Typing

    第四十九节 鸭子类型Duck Typing 前言 实践 前言 本节我们一起学习一个非常有趣的知识点:鸭子类型.有这么一句话:If it walks like a duck, and it quacks ...

  2. duck typing java_编程语言中的鸭子类型 Duck Typing

    来源 | https://segmentfault.com/a/1190000019607240 1.什么是鸭子类型(duck typing) 百度百科是这样解释的: 这是程序设计中的一种类型推断风格 ...

  3. 编程语言中的鸭子类型 Duck Typing

    来源 | https://segmentfault.com/a/1190000019607240 1.什么是鸭子类型(duck typing) 百度百科是这样解释的: 这是程序设计中的一种类型推断风格 ...

  4. Python笔记 · 鸭子类型 / Duck Typing

    1. 问题的由来 我初次意识到鸭子类型的存在是在学习Sklearn时,在<Hands-On Machine Learing>一书的第二章,作者提供了一个自定义的Tansformer,使用自 ...

  5. 鸭子类型duck typing(动态)

    在程序设计中,鸭子类型(duck typing)是动态类型的一种风格.在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定.这个概念的名字来源于由Ja ...

  6. Python学习笔记——鸭子类型(duck typing)

    前言 在实习期间,由于工作需要首次接触了Python这门语言,由于学习和使用的时间非常短,所以当时认为,作为一门解释性语言,在做Web开发方面,Python和PHP的差别不大,甚至在一些应用场景上没有 ...

  7. [转]编程语言中的 鸭子模型(duck typing)

    在学习Python的时候发现了鸭子类型这个术语,听起来好像很有意思一样,所以把它记下来. 鸭子类型的核心概念在于一个对象的有效语义,不是继承自特定的类或者实现特定的方法,而是 由当前的属性和方法集合决 ...

  8. python中的鸭子类型

    浅层理解 走路像鸭子,说话像鸭子,它就是鸭子 深层理解 指的是面向对中,子类不需要显示的继承某个类,只要有某个的方法和属性,那我就属于这个类 编程语言中的鸭子类型说明 假设有个鸭子类Duck类,有两个 ...

  9. 【python 笔记/小白快速入门python】python浅谈(一)犹抱琵琶半遮面

    python浅谈(一)犹抱琵琶半遮面 继浅谈(零)初识庐山真面目[https://blog.csdn.net/HarryOtter/article/details/90519877 ] 之后,终于窥得 ...

最新文章

  1. 智能睡眠评估系统(包含:睡眠数据特征工程、睡眠评分、睡眠聚类、睡眠可视化分析、睡眠结论存储)
  2. SAP PP使用ECR去修改BOM主数据
  3. 让linux的防活墙也像windows一样简单易用
  4. xml学习总结(三)
  5. php 比java 快_php比java要快在哪里
  6. Java FilterInputStream reset()方法与示例
  7. 1流明等于多少lux_光通量(流明)和照度(勒克司)定义及换算关系
  8. python导入matplotlib模块_从NumPy导入python子模块有什么区别,matplotlib包
  9. 织梦dedecms怎么改模板
  10. LeetCode - 720 - 词典里最长的单词(longest-word-in-dictionary)
  11. 香港黄金配角吴孟达去世,80后程序员以轮播图来悼念达叔,达叔一路走好!
  12. 修复下载后已发生损坏的压缩包(.rar)文件
  13. 7-4 韩信点兵 (10 分)
  14. off-by-onedoublefree. 看雪10月ctf2017 TSRC 第四题赛后学习
  15. Google推荐的15条HTML 5代码军规
  16. 高级转录组调控分析和R语言数据可视化第十三期 (线上/线下同时开课)
  17. 关于英语的大小写规则
  18. 分享125个ASP源码,总有一款适合您
  19. git拉取指定分支上面的代码 提交本地分支到远程
  20. 劳务报酬所得税java程序计算

热门文章

  1. 神奇的「小黄鸭调试法」
  2. R语言数学建模(4)模式甄别
  3. javascrip中UMD规范
  4. 107. 面向过程和面向对象
  5. 微信头像昵称获取能力的变化导致了我半年没更新小程序
  6. c++之epoll原理解析与Client Server功能实现
  7. python数据分析之单因素分析(线性拟合)
  8. 从猫蛇之战再看内核戏CPU
  9. VR全息教育实训中心教学系统、全息教育实训室的全息教学一体机
  10. Java设计模式之秒杀系统