09-04 多态性与鸭子类型

多态与多态性

多态指的是一类事物有多种形态,比如动物有多种形态:猫、狗、猪

class Animal: #同一类事物:动物
    def talk(self):
        pass
class Cat(Animal): #动物的形态之一:猫
    def talk(self):
        print(‘喵喵喵‘)
class Dog(Animal): #动物的形态之二:狗
    def talk(self):
        print(‘汪汪汪‘)
class Pig(Animal): #动物的形态之三:猪
    def talk(self):
        print(‘哼哼哼‘)

#实例化得到三个对象
>>> cat=Cat()
>>> dog=Dog()
>>> pig=Pig()

插图:恶搞图34

多态性指的是可以在不用考虑对象具体类型的情况下而直接使用对象,这就需要在设计时,把对象的使用方法统一成一种:例如cat、dog、pig都是动物,但凡是动物肯定有talk方法,于是我们可以不用考虑它们三者的具体是什么类型的动物,而直接使用

>>> cat.talk()
喵喵喵
>>> dog.talk()
汪汪汪
>>> pig.talk()
哼哼哼

更进一步,我们可以定义一个统一的接口来使用

>>> def Talk(animal):
...     animal.talk()
...
>>> Talk(cat)
喵喵喵
>>> Talk(dog)
汪汪汪
>>> Talk(pig)
哼哼哼

插图:恶搞图35

Python中一切皆对象,本身就支持多态性

# 我们可以在不考虑三者类型的情况下直接使用统计三个对象的长度
s.__len__()
l.__len__()
t.__len__()

# Python内置了一个统一的接口
len(s)
len(l)
len(t)

插图:恶搞图36

多态性的好处在于增强了程序的灵活性和可扩展性,比如通过继承Animal类创建了一个新的类,实例化得到的对象obj,可以使用相同的方式使用obj.talk()

>>> class Wolf(Animal): #动物的另外一种形态:狼
...     def talk(self):
...         print(‘嗷...‘)
...
>>> wolf=Wolf() # 实例出一头狼
>>> wolf.talk() # 使用者根本无需关心wolf是什么类型而调用talk
嗷...

插图:恶搞图37

综上我们得知,多态性的本质在于不同的类中定义有相同的方法名,这样我们就可以不考虑类而统一用一种方式去使用对象,可以通过在父类引入抽象类的概念来硬性限制子类必须有某些方法名

import abc

# 指定metaclass属性将类设置为抽象类,抽象类本身只是用来约束子类的,不能被实例化
class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod # 该装饰器限制子类必须定义有一个名为talk的方法
    def talk(self): # 抽象方法中无需实现具体的功能
        pass

class Cat(Animal): # 但凡继承Animal的子类都必须遵循Animal规定的标准
    def talk(self):
        pass

cat=Cat() # 若子类中没有一个名为talk的方法则会抛出异常TypeError,无法实例化

插图:恶搞图38

但其实我们完全可以不依赖于继承,只需要制造出外观和行为相同对象,同样可以实现不考虑对象类型而使用对象,这正是Python崇尚的“鸭子类型”(duck typing):“如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子”。比起继承的方式,鸭子类型在某种程度上实现了程序的松耦合度,如下

#二者看起来都像文件,因而就可以当文件一样去用,然而它们并没有直接的关系
class Txt: #Txt类有两个与文件类型同名的方法,即read和write
    def read(self):
        pass
    def write(self):
        pass

class Disk: #Disk类也有两个与文件类型同名的方法:read和write
    def read(self):
        pass
    def write(self):
        pass

插图:恶搞图39

原文地址:https://blog.51cto.com/egon09/2467628

时间: 2024-08-28 23:20:42

09-04 多态性与鸭子类型的相关文章

面向对象之组合、封装、多态性、鸭子类型

一.组合 1. 什么是组合 一个对象的属性是来自于另外一个类的对象,称之为组合 2. 为何用组合 组合也是用来解决类与类代码冗余的问题 3. 如何用组合 # class Foo: # aaa=1111 # def __init__(self,x,y): # self.x=x # self.y=y # # def func1(self): # print('Foo内的功能') # # # class Bar: # bbb=2222 # def __init__(self, m, n): # sel

【我的书】Unity Shader的书 — 目录(2015.09.04更新)

写在前面 感谢所有点进来看的朋友.没错,我目前打算写一本关于Unity Shader的书. 出书的目的有下面几个: 总结我接触Unity Shader以来的历程,给其他人一个借鉴.我非常明白学Shader的艰难,在群里也见了很多人提出的问题.我觉得学习Shader还是一件有规律可循的事情,但问题是中文资料难觅,而大家又不愿意去看英文...这对我有什么好处呢?强迫我对知识进行梳理,对细节问题把握更清楚. 第二个原因你懂的. 关于本书的定位问题: 面向Unity Shader初学者,但要: 有一定的

Objective-C 编程全解-第04章 对象的类型和动态绑定

第04章 对象的类型和动态绑定 Objective-C的一个重要特征就是动态性,本章将对Objective-C的动态类型(dynamic typing)和动态绑定(dynamic binding)进行说明. 4.1 动态绑定 4.1.1 什么是动态绑定 Objective-C中的消息是在运行时才去绑定的.运行时系统首先会确定接受者的类型(动态类型识别),然后根据消息名在类的方法列表里选择相应的方法执行,如果没有找到就到父类中去继续寻找,假如一直找到NSObject也没有找到就要调用的方法,就会报

16 Apr 18 封装的property 多态 鸭子类型 classmethod和staticmethod

16 Apr 18 一.      封装的property BMI指数(bmi是计算而来的,但很明显它听起来像是一个属性而非方法,如果我们将其做成一个属性,更便于理解) 成人的BMI数值: 过轻:低于18.5 正常:18.5-23.9 过重:24-27 肥胖:28-32 非常肥胖, 高于32 体质指数(BMI)=体重(kg)÷身高^2(m) 首先需要明确.bmi是算出来的,不是一个固定死的值,也就说我们必须编写一个功能,每次调用该功能都会立即计算一个值,但很明显人的bmi值听起来更像一个名词而非

封装之property,多态,鸭子类型,classmethod与staticmethod

一.封装之Property prooerty是一种特殊的属性,访问时他会执行一段功能(函数)然后返回 '''BMI指数(bmi是计算而来的,但很明显它听起来像是一个属性而非方法,如果我们将其做成一个属性,更便于理解) 成人的BMI数值:过轻:低于18.5正常:18.5-23.9过重:24-27肥胖:28-32非常肥胖, 高于32 体质指数(BMI)=体重(kg)÷身高^2(m) EX:70kg÷(1.75×1.75)=22.86 ''' class People: def __init__(se

python多态和鸭子类型

多态 多态是同一个行为对于不同的对象具有多个不同表现形式或形态的能力. 多态性是对象多种表现形式的体现. 比如 我们按下 F1 键这个动作: 如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档: 如果当前在 Word 下弹出的就是 Word 帮助: 在 Windows 下弹出的就是 Windows 帮助和支持. 同一个事件发生在不同的对象上会产生不同的结果. 文件有多种形态:文本文件,可执行文件 import abc # 抽象类 class File(metaclass=abc.AB

python语言的鸭子类型和强类型语言的多态

前面讲接口类的时候举过一个有关支付方式的例子,支付方式可以有几种,微信支付,支付宝支付,苹果支付等,这几个不同的支付都统一于支付,像这样几个类都统一于 某一个类或者某一个方法,或者说一个类有不同的形态的情况就属于多态:虽然几种支付方式都归一于支付类,执行的方法一样,但是每一个支付方式都有自己的特性,实现的 形态也不一样,即为多态性. class Payment: # 必要的父类 def pay(self,money): pass class Wechatpay(Payment): # 子类继承父

面向对象的三大特性 鸭子类型 类的约束 super的深度剖析

1.三大特性 封装 ? 把很多数据封装到?个对象中. 把固定功能的代码封装到?个代码块, 函数, 对象, 打包成模块. 这都属于封装的思想. 具体的情况具体分析. 比如. 你写了?个很?B的函数. 那这个也可以被称为封装. 在?向对象思想中. 是把?些看似?关紧要的内容组合到?起统?进?存储和使?. 这就是封装. 继承 ? ?类可以?动拥有?类中除了私有属性外的其他所有内容. 说?了, ??可以随便?爹的东?. 但是朋友们, ?定要认清楚?个事情. 必须先有爹, 后有??. 顺序不能乱, 在py

什么是鸭子类型(duck typing)

"当看到一只鸟走起来像鸭子.游泳起来像鸭子.叫起来也像鸭子,那么这只鸟就可以被称为鸭子." 我们并不关心对象是什么类型,到底是不是鸭子,只关心行为. 比如在python中,有很多file-like的东西,比如StringIO,GzipFile,socket.它们有很多相同的方法,我们把它们当作文件使用. 鸭子类型在动态语言中经常使用,非常灵活,使得python不想java那样专门去弄一大堆的设计模式. 下面例子用duck typing来实现多态. #coding=utf-8 class