Python是一种多态语言,其表现特征是:对象方法的调用方只管方法是否可调用,不管对象是什么类型,从而屏蔽不同类型对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。
一、    Python中的协议
Python中定义某种类型是以实现了该类型对应的协议为标准的,如 可迭代对象(Iterable) 是指实现了可迭代协议的对象类型,迭代器是实现了迭代器协议的对象类型,序列是实现了序列协议的对象类型,那么具体协议是什么呢?在Python中协议是指一个或一组可供外部访问对象的特定方法(也有把对象属性作为协议的一部分,但老猿并不推荐这种使用方式),如可迭代对象是指容器中的元素可以通过__iter__( )方法或__getitem__( )方法访问,迭代器协议必须是定义和实现了__iter__()方法和next()方法,序列协议必须实现__len__()和getitem()方法。
协议是正式的,没有强制力,可以根据具体场景实现一个具体协议的一部分。例如,为了支持迭代,只需实现__getitem__,不需要实现__len__。

二、    “鸭子类型”与多态
从Python中协议的使用可以得出,Python中的对象类型不是简单的以类型定义区分的,而是以对象是否提供了特定的访问方法来确认的。凡是实现了类型要求的方法的对象都可以看做遵守类型对应协议,就是该类型的对象,老猿理解这是Python中多态的本质,这种以协议确认类型的方法所确认的类型就是“鸭子类型”(Duck typing)。
为什么说是“鸭子类型”呢?这个所有关于“鸭子类型”介绍的文章都有共同的介绍,在这复述一下:
鸭子类型(英语:duck typing)是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由"当前方法和属性的集合"决定。
鸭子类型这一名字出自美国James Whitcomb Riley(有的材料说他是诗人,有的说他是测试人员,在此就不探究了)提出的如下的表述:
“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.”当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。
简单归纳就是:对象的类型不再由继承等方式决定,而由实际运行时所表现出的具体行为来决定。
以下为定义的鸭子类型与人类型,它们都有相同的方法:
class Duck():
  def walk(self):
    print('I walk like a duck')
  def swim(self):
    print('I swim like a duck')
  def quack(self):
    print('I quack like a duck')

class Person():
  def walk(self):
    print('this one walk like a duck') 
  def swim(self):
    print('this man swim like a duck')
def quack(self):
    print('I quack like a duck')

类的定义语法在后面一节介绍,但大家应该明白上述两个类的定义。可以很明显的看出,Person类拥有跟Duck类一样的方法,当有一个函数调用Duck类,并利用到了三个方法walk()、swim()和quack()。我们传入Person类也一样可以运行,函数并不会检查对象的类型是不是Duck,只要他拥有这三个方法,就可以正确的被调用。
为什么Python的多态是由“鸭子类型”来实现呢?这是由于Python属于动态语言,Python在定义变量时不指定变量的类型,而是由解释器根据变量内容推断变量类型的(也就是说变量的类型取决于所关联的对象),因此Python在判断变量类型时是看变量所具有的功能(方法)来决定。这就造就了Python的这种非常神奇的多态和“鸭子类型”,也是开发者很喜欢的一种开放的程序开发风格。

三、    鸭子类型的优点
1.    python中的鸭子类型允许我们使用任何提供所需方法的对象,而不需要迫使它成为一个子类;
2.    因为任何提供正确接口的对象都可以在python中交替使用,它减少了多态的一般超类的需求。继承仍然可以用来共享代码,但是如果所有被共享的都是公共接口,鸭子类型就是所有所需的。这减少了继承的需要,同时也减少了多重继承的需要;
3.    调用方只管调用,不管细节,不管对象是什么类型,从而可以屏蔽不同类型对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。

三、    鸭子类型编程的注意事项
1.    “鸭子类型”关注是对象的方法,而不是类型,因此使用Python开发时,尽量不要使用诸如type、issubclass等函数显式地执行类型检查进行类型检查;
2.    在进行方法调用时,对于程序无法明确确认对象是否有相应方法时,可以使用异常捕获或者hasattr或callable检查所需的方法是否存在来确保对应方法可以正常调用。如果有个对象p,我们需要判断p是否有swim方法,有如下方式:
1)    使用hasattr,语句:if hasattr(p,'swim') :p.swim()
2)    使用callable,语句:if hasattr(p,'swim')  and  callable(p.swim):p.swim()
3)    使用callable,语句:if  callable(getattr(p,'swim',None)):p.swim()

本节介绍了Python中协议和“鸭子类型”的概念,并说明了Python多态与“鸭子类型”的关系,同时分析了“鸭子类型”有点以及使用的注意事项。
老猿Python(https://blog.csdn.net/LaoYuanPython)系列文章用于逐步介绍老猿学习Python后总结的学习经验,这些经验有助于没有接触过Python的程序员可以很容易地进入Python的世界。
欢迎大家批评指正,谢谢大家关注!

转载于:https://www.cnblogs.com/LaoYuanPython/p/11087710.html

第7.3节 Python特色的面向对象设计:协议、多态及鸭子类型相关推荐

  1. Python面向对象,类,继承,多态及鸭子类型,获取类的类型,方法和属性(类似java的反射)

    1.创建类的代码: #在Java中,所有的最终父类都是Object #在python中也是,一个类没有直接的父类就写入objectclass Animal(object):#在python中init方 ...

  2. python多态和鸭子类型

    概述 python是一门解释语言,但是同java等静态语言一样,是可以通过继承的方式实现多态.而且python还有一个自己的特殊实现多态的方法,就是通过鸭子类型,来实现多态. 继承多态 通过严格的继承 ...

  3. Python多态、鸭子类型

    一.多态 多态指的是一类事物有多种形态. 动物有多种形态:人,狗,猪 import abc class Animal(metaclass=abc.ABCMeta): #同一类事物:动物 @abc.ab ...

  4. Python多态与鸭子类型

    学习到多态的时候,不确定自己是否完全理解了python的多态,于是Google观看了众多资料和文献,发现很多编程大佬讲得过于抽象,不便于新手理解,这违背了python的初衷:简单. 所以我在此用通俗一 ...

  5. 面向对象的接口类 以及鸭子类型

    1.接口类,抽象类. 2.鸭子类型(Python多态)(Python三大特性之一)Python封装 1.接口类和抽象类只是在工作中书写的一种规范. class QQ: def  pay(self,mo ...

  6. Python语言特性和优缺点及什么是鸭子类型?

    1)Python语言特性? Python是静态还是动态类型?是强类型还是弱类型?         Python是动态强类型语言(不少人误以为是弱类型) 动态还是静态指的是编译期还是运行期确定类型 强类 ...

  7. 面向对象—多态、鸭子类型(Day21)

    编程原则java具有自己的编程原则和设计模式,不能多继承.python的编程原则:1.开放封闭原则:开放是对扩展是开放的,封闭是对修改是封闭的(已经写完的代码程序是不能修改的).2.依赖倒置原则:高层 ...

  8. java实现鸭子类型_面向对象—多态、鸭子类型(Day21)

    编程原则java具有自己的编程原则和设计模式,不能多继承. python的编程原则: 1.开放封闭原则:开放是对扩展是开放的,封闭是对修改是封闭的(已经写完的代码程序是不能修改的). 2.依赖倒置原则 ...

  9. Python之多态与鸭子类型

    一.多态与多态性 多态指的是一类事物有多种形态,比如动物有多种形态:猫.狗.猪 class Animal: # 同一类事物:动物def talk(self):pass class Cat(Animal ...

  10. python 接口(抽象) 多态,鸭子类型, 多继承原理(mro)

    抽象类与接口类 接口类 继承有两种用途: 一:继承基类的方法,并且做出自己的改变或者扩展(代码重用) 二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数 ...

最新文章

  1. Python type hints 之 Optional,Union
  2. MySQL简单查询性能分析
  3. lumen 支持多文件上传及php 原生多文件上传
  4. 报错:selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This versio
  5. W4_python_decorator_generator_Iteratable_Iterator_json_pickle
  6. 【转】Vue.js入门教程(二)在页面中引入vue的方式
  7. 编辑器,webstorm,phpstorm系列配置方法汇总-笔记
  8. 微信小程序入门三:轮播图
  9. 3D 机器视觉 02 - FPGA生成N位元格雷码
  10. 【Landsat 8】介绍
  11. Luogu2216 [HAOI2007]理想的正方形
  12. 第一章 时间序列基础知识
  13. 20道你必须要背会的微服务面试题,面试一定会被问到
  14. Java class对象说明 Java 静态变量声明和赋值说明
  15. docker更换国内镜像(网易docker镜像)解决docker下载镜像慢问题
  16. 一口气搞懂「Flink Metrics」监控指标和性能优化,全靠这33张图和7千字(建议收藏)
  17. 鼠标垫测试软件,百款鼠标垫测试(项目)
  18. jQuery笔试题汇总整理--2018
  19. 基于51单片机的智能加湿器控制proteus仿真系统设计
  20. android仿百度地图悬浮式窗口,百度地图(bMap)实现浮动层、按钮等的方法及代码...

热门文章

  1. matlabif函数多个条件并列_sql课堂笔记-窗口函数
  2. python语言适用于哪些领域_Python用于哪些领域
  3. pythonATM,购物车项目实战3-视图函数
  4. java 判断double是否为整数_java 中如何判断输入的是int还是double
  5. 计算机的排除故障的方法,计算机产生故障的原因和排除故障的方法
  6. java反射加载类_Java反射 - 动态类加载和重载
  7. Linux下nautilus的右键快捷菜单项设置
  8. 从MySQL复制功能中得到一举三得实惠
  9. Windows之远程访问×××的简单部署
  10. 2月26日 Scrapy入门