Python___鸭子类型 与 多态

原文

1、什么是“鸭子类型”

所谓 鸭子类型 就是:如果一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么它就是鸭子。这个概念的名字来源于 James Whitcomb Riley 提出的鸭子测试。

鸭子类型(英语:duck typing)在程序设计中是动态类型的一种风格。

在鸭子类型中,关注点在于对象的行为能做什么;而不是关注对象所属的类型。

  • 在常规类型中,我们能否在一个特定场景中使用某个对象取决于这个对象的类型,
  • 而在鸭子类型中,则取决于这个对象是否具有某种属性或者方法——即只要具备特定的属性或方法,能通过鸭子测试,就可以使用。
    如果这些需要被调用的方法不存在,那么将引发一个运行时错误。任何拥有这样的正确的调用的方法的对象都可被函数接受的这种行为。

具体来说,就是:

  • 在不使用鸭子类型的语言中: 我们可以编写一个函数泛型设为<鸭子>,它接受一个类型为"鸭子"的对象,并调用它的"走"和"叫"方法。
    此时:鹅不是鸭子,鹅永远也能不被当成鸭子
  • 在使用鸭子类型的语言中: 我们可以编写一个函数可以接受一个任意类型(且实现"走"和"叫"方法)的对象,并调用它的"走"和"叫"方法。
    此时:鹅不是鸭子,但是鹅拥有鸭子"走"和"叫"的方法,在上面的函数中就可以被当成鸭子了

因此不难看出:
鸭子类型的好处就在于:
能够避免一些类的重写,无需大量复制相同的代码

鸭子类型使用的前提是
需要良好的文档支持,不然会让代码变得很混乱,如果没有良好的文档及说明,有可能会导致你的“鸭子”不是我的“鹅”了

补个类似的概念:协议:

在面向对象编程中,协议是非正式的接口,是一组方法,只由文档和约定定义,因此,协议不能像正式接口那样施加强制性约束。而 Python 的哲学就是尽量支持基本协议。

协议和接口的区别是:

  1. 实现接口就要实现接口的所有的方法
  2. 而协议是不是强制性的约定,如果你不遵守协议(没有实现部分方法),也无所谓,运行时报错就是了。

使用鸭子类型:多态

先来看看“多态”
简单来说,定义时的类型和运行时的类型不一样就是多态

多态是指一类事物有多种形态。
比如动物有多种形态,人、狗、猫等等
例如文件,文件有多种形态:文本文件、可执行文件
总而言之,多态即某类的再分类,再分的每一类就是父类的多种形态的一种

对于Java这一类强类型语言:多态表现在可以用<父类>的集合接住子类的实例化对象。

而对于python的鸭子模式,下面代码就是指:

  • 把Cat,Dog,Duck当成变量放入(可以包含所有类型数据的)集合list
  • 在最后使用时实例化调用类方法的时候才会明白是一个类,这就表示多态
class Cat(object):
    def info(self):
        print("我是一只猫")


class Dog(object):
    def info(self):
        print("我是一只狗")


class Duck(object):
    def info(self):
        print("我是一只鸭")

list=[Cat,Dog,Duck]
for animal in list:
    animal().info()
posted @ 2022-06-02 09:32  kingwzun  阅读(160)  评论(0编辑  收藏  举报