79、Python之鸭子类型:没有听过鸭子类型?关键在于认知的转变

news2024/11/24 20:08:31

引言

不同于Java等静态类型的语言,Python基于动态类型系统的设计理念,使得Python在很多应用场景中,显得更急灵活、高效。而在动态类型系统中,有一个很重要的概念,就是“鸭子类型”。鸭子类型的背后,代表的是一些编程认知方式的转变,是对“协议”、“行为”与类型之间关系的更加深入的理解。

本文的主要内容有:

1、什么是鸭子类型

2、简单对比Python与Java的类型系统

3、鸭子类型的应用

4、鸭子类型的注意事项

什么是鸭子类型

所谓“鸭子类型(Duck Typing)”,是一种动态类型系统的编程概念。其核心思想来自于詹姆斯·惠特科姆·莱利的鸭子测试:“如果它走起来像鸭子,叫起来像鸭子,那么它就是鸭子”。

换句话说,在鸭子类型中,对象的有效性不依赖于其显式的类型,而是依赖于对象是否具有所需要的属性和方法。

可以粗略的理解为,所谓的实体的强类型,更像是一种标签。而我们在实际业务场景中,需要的是某些能力、行为。所以,只要某个实体对象,具备了我们所需要的能力,能够在系统交互中实现所需要的行为,那么至于这个实体对象被标记为什么类型,其实并不是很重要。

以“捉老鼠”的场景为例,我们最根本的诉求是不被老鼠所影响,想到的方法,或者需要具备的能力是“能够把老鼠捉起来”。至于是白猫、黑猫、多管闲事的狗,又或者是有些屠龙技的人,只要能达到捉到老鼠的目的即可。

所以,本质上来说,在动态类型系统中,我们所关注的不再是静态类型系统中,一个实体对象所属的类型,而是这个实体对象所具备的属性和方法。而所应该具备的属性和方法,更加抽象来说,叫做“协议”。所以,我们的关注视角,从具体类型转换到了协议。能理解了这一个认知的转换,就已经理解了鸭子类型的本质。

简单对比Python与Java的类型系统

如果有同学比较熟悉Java,应该能够深刻地感受到,在Java的编程世界中,类型系统是静态的,类型检查是在编译时进行的,并且对象的类型是显式声明的。这样的好处在于,有些错误可以在编译期就能提早发现。但是,也会导致更多的强制类型转换、一大堆样板代码等。

在Java中,如果我们定义不同动物,定义一个函数接收具体的动物对象,发出不同的叫声,我们大概需要这样做:

package com.study;

interface Animal {
    void bark();
}
class Dog implements Animal {
    @Override
    public void bark() {
        System.out.println("小狗汪汪汪");
    }
}
class Duck implements Animal {
    @Override
    public void bark() {
        System.out.println("鸭子嘎嘎嘎");
    }
}
public class Zoo {
    public static void make_sound(Animal animal) {
        animal.bark();
    }

    public static void main(String[] args) {
        Dog dog = new Dog();
        make_sound(dog);
        Duck duck = new Duck();
        make_sound(duck);

    }
}

需要先有一个表示动物的类型,可以是一个接口或者抽象类,用于指向具体的动物子类型的对象。

定义对象,还要明知道类型,再手动显式声明类型。

运行结果:

27db4bd6bdd45bcbe34996614c493b9e.jpeg

这是一套标准的面向对象的继承的设计实现,也确实达到了我们想要的效果。

在Python中,我们也可以通过面向对象的继承的思路,来实现同样的效果。但是,由于Python是动态类型的,我们还可以有更简化的实现方式:

class Dog:
    def bark(self):
        print('小狗汪汪汪')


class Duck:
    def bark(self):
        print('鸭子嘎嘎嘎')


def make_sound(animal):
    animal.bark()


if __name__ == '__main__':
    dog = Dog()
    make_sound(dog)
    duck = Duck()
    make_sound(duck)

从代码行数的角度,依然能看到更加简洁。

从设计实现上,Dog和Duck两个类型没有任何继承关系(当然都是object类的子类,这点这里可以忽略)。它们定义了同样的方法bark(),所以在进行函数make_sound()调用时,只要传入的对象实例具有bark()方法,就能成功执行。

执行结果:

0f60d9a531c88f08dc9aa2eb9dcea8fb.jpeg

从上面的对比可以看出,Python中,类型的检查是运行时进行的,类型是隐式的。Python中的鸭子类型的存在,允许我们更加专注于对象的行为,而非其必须是某个特定类型,或者繁琐地进行类型继承关系的设计。

鸭子类型的应用

1、编程的灵活性和多态性

鸭子类型的引入,首先给我们提供了一种新的“多态”的思路,我们不需要进行类的继承体系的设计,不需要考虑抽象出具有特定功能的公共父类,只需要定义同样的行为方法即可。这种实现多态的方式,似乎是一种更加自然的方式。

2、代码的简洁性

鸭子类型减少了类型检查和类型转换的需求,从而使得代码更加简洁易读。在Java中,通常需要通过强制转换来实现多态行为。而在Python中,这些都变得不是必要的。

3、兼容性和扩展性

鸭子类型使得代码更加具有兼容性和可扩展性。之所以这样说,是因为,我们可以随时定义新的对象类型,只要定义特定的方法,就可以将新的类型的对象,传递给一个现有的函数。这样,使得对现有功能的扩展变得更加灵活、方便。

鸭子类型的注意事项

需要说明的是,虽然鸭子类型是我们接下来几篇文章的主角,但是还是有一些潜在的需要注意的事项:

1、运行时错误

由于类型检查被推迟到了运行时进行,所以,有些错误只有在实际运行代码时,才会被发现。所以,良好的测试变得更加重要。

2、代码的可读性

对于新手或者不熟悉代码库的开发者来说,鸭子类型在一定程度上会导致代码可读性的降低。所以,适当的注释和文档说明,也变得更加重要了。

总结

本文重点介绍了“鸭子类型”背后的核心理念,专注于行为而非类型本身。同时,对比了Java和Python这两种语言所代表的类型系统的差别,尤其在多态实现上的差异。尽管“鸭子类型”赋予了Python极大的灵活性和简洁性,但是,还是需要注意这些有点背后潜在的风险。

感谢您的拨冗阅读,希望对您有所帮助。

678e6f4ab958e369d1ba505a781d2f9c.jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2164191.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一地通过率高达46.43%!为什么都说软考难?

从2023年上半年到2024年上半年,近三次考试,几个考区的软考通过率基本不超过13%。 然而根据近日陕西省科技资源统筹中心公布的数据,从1987年到2024年,陕西软考的总拿证率竟然高达46.43%。软考真的有大家认为的那么难吗?…

Unity场景内画车道线(根据五阶曲线系数)

之前做过使用Dreamteck Splines插件构建车道线之前需求是给定车道线的点位,根据点位来进行构建。 由于AI识别出来的点位不线性,画出来的车道线经常是歪七扭八,所以使用五阶曲线系数进行构建。 使用在线图形计算器进行测试构建,公式…

DATEDIF 函数用不了?DATEDIF函数怎么用我来告诉你

大家好,这里是效率办公指南! 📅 在处理与时间相关的数据时,DATEDIF函数是Excel中一个非常有用的工具。DATEDIF函数可以计算两个日期之间的差异,无论是天数、月数还是年数。这在处理年龄计算、工龄统计或任何需要日期差…

大健康管理系统|健康综合咨询问诊平台设计与实现(源码+数据库+文档)

大健康管理系统目录 目录 健康综合咨询问诊平台设计与实现 一、前言 二、系统功能设计 三、系统实现 5.1用户信息管理 5.2 医生信息管理 5.3科室信息管理 5.1新闻信息管理 四、数据库设计 1、实体ER图 2、具体的表设计如下所示: 五、核心代码 六、论文…

docker笔记_数据卷、挂载

docker数据存储 概述数据卷(Volumes)特点操作 绑定挂载(Bind Mounts)内存挂载(tmpfs)总结 概述 镜像构建过程中,所产生的layer都是只读层,只有在创建容器时才会生成一个可写的容器层…

鸿蒙OpenHarmony【小型系统基础内核(虚拟内存管理)】子系统开发

虚拟内存管理 基本概念 虚拟内存管理是计算机系统管理内存的一种技术。每个进程都有连续的虚拟地址空间,虚拟地址空间的大小由CPU的位数决定,32位的硬件平台可以提供的最大的寻址空间为0-4GiB。整个4GiB空间分成两部分,LiteOS-A内核占据3Gi…

Go weak包前瞻:弱指针为内存管理带来新选择

在介绍Go 1.23引入的unique包的《Go unique包:突破字符串局限的通用值Interning技术实现》一文中,我们知道了unique包底层是基于internal/weak包实现的,internal/weak是一个弱指针功能的Go实现。所谓弱指针(Weak Pointer,也称为弱…

算法分享——《滑动窗口》

🚍《长度最小的子数组》 🚲题目描述: 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl1, ..., numsr-1, numsr] ,并返回其长度**。**如果不存在符…

Linux进程状态与进程优先级

目录 Linux进程状态与进程优先级 前置知识 并行与并发 时间片 进程状态 基本介绍 等待状态的本质 swap分区 Linux进程状态 Linux进程状态分类 运行状态(Running)与等待状态(Sleeping) 硬盘等待状态(Disk S…

计算机视觉必备模型YOLO系列模型的知识点,提供YOLOv1-v8模型结构与代码实例

大家好,我是微学AI,今天给大家介绍一下计算机视觉必备模型YOLO系列模型的知识点,提供YOLOv1-v8模型结构与代码实例。本文全面介绍了计算机视觉领域中必备的YOLO系列模型,详细梳理了YOLOv1至YOLOv8模型的结构及其演变过程。文章内容…

Node.js 学习 path模块、fs模块、npm软件包管理器、导出、导入

目录 1.Node.js入门 1.1 什么是 Node.js 1.2 fs模块-读写文件 1.3 path模块-路径处理 1.4 案例-压缩前端html 1.5 认识URL中的端口号 1.6 http模块-创建Web服务 1.7 案例-浏览时钟 2.Node.js 模块化 2.1 模块化简介 2.1.1 什么是模块化? 2.1.2 CommonJS…

【软件建设方案】设备管理系统建设方案(Doc原件参考)

1.系统概述 1.1.需求描述 1.2.需求分析 1.3.重难点分析 1.4.重难点解决措施 2.系统架构设计 2.1.系统架构图 2.2.关键技术 3.系统功能设计 3.1.功能清单列表 3.2.设备信息数据库 3.3.设备维护计划管理子系统 3.4.设备维护管理子系统 3.5.备件物资管理子系统 3.6.…

1区IEEE-Trans发文暴涨3倍,CCF-B类,刚跌出了TOP榜!这是不是官方提前发出警告?

【SciencePub学术】今天给大家推荐的是1本地球科学领域的SCI—《IEEE TRANSACTIONS ON GEOSCIENCE AND REMOTE SENSING》,IEEE-Trans系列,并且是CCF-B类期刊!此系列的期刊在业界的权威性还是不容置疑的。 优点VS缺点 ✦ IEEE-Trans系列 ✦ C…

普通本科生也能成为AI高手:人工智能学习指南

在人工智能(AI)日益普及的今天,许多人都渴望掌握这项技术,但常有人疑惑:没有顶尖学府的背景,我也能学习人工智能吗? 答案是肯定的! 人工智能是一个充满机遇与挑战的领域&#xff0c…

渗透测试工具 sqlmap 基础教程

一、引言 在网络安全领域,渗透测试是一项至关重要的工作,它可以帮助我们发现系统中的安全漏洞,从而采取相应的措施进行修复。而 sqlmap 作为一款强大的开源渗透测试工具,专门用于检测和利用 SQL 注入漏洞。本文将为大家详细介绍 …

HTTP 1.0 2.0 3.0详解

HTTP HTTP全称超文本传输协议,是一种属于应用层的通信协议。它允许将超文本标记语言文档(HTML)从Web服务器传输到客户端的浏览器。 HTTP报文结构 请求报文结构 请求方法: GET:一般用来请求已被URI识别的资源&#x…

Elasticsearch7.7.1集群不能相互发现的问题解决以及Elasticsearch7.7.1安装analysis-ik中文分词插件的应用

一、Elasticsearch7.7.1集群不能相互发现的问题解决 在使用elasticsearch7.7.1搭建集群,使用了3台服务器作为节点,但在搭建的过程中发现每台服务器的elasticsearch服务都正常,但是不能相互发现,期间进行了一些配置的修改偶尔出现了…

(附源码)SSM养老院综合服务管理系统-计算机毕设 23237

基于SSM的养老院综合服务管理系统 摘 要 21世纪的今天,随着社会的不断发展与进步,人们对于信息科学化的认识,已由低层次向高层次发展,由原来的感性认识向理性认识提高,管理工作的重要性已逐渐被人们所认识,…

助力解析化学图像生成文本分析,化学大语言模型 ChemVLM 来啦!

ChemVLM 是由上海人工智能实验室于 2024 年推出的首个面向化学领域的开源多模态大型语言模型。该模型旨在解决化学图像理解与文本分析之间的不兼容问题,通过结合视觉 Transformer (ViT)、多层感知机 (MLP) 和大型语言模型 (LLM) 的优势,实现了对化学图像…

万维组态介绍

演示地址:http://121.40.16.189:12000 万维组态本地部署文档万维组态线上部署文档万维组态操作说明文档万维组态接入文档万维组态绑点示例文档万维组态接入源代码说明万维组态扩展图元示例文档万维组态大屏图元示例文档 项目介绍 万维组态是一款功能强大的基于Web的…