版权声明:本文为CSDN博主「yuanzhoulvpi」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yuanzhoulvpi/article/details/127525892

===============================================

背景
大部分学python的朋友,可能都知道听说过鸭子类型。其实类型,就是那种会发出嘎嘎叫的类型,就叫类型(bushi,开玩笑的)
大部分学python的朋友,可能也都知道python也有所谓的静态类型检测。
那么 protocol和鸭子类型和类型检测到底是什么关系,这里我们来介绍一下。

详细介绍

类型检测

在写python的时候,大部分人可能是这么写的:

def cal_sum(x, y):
res = x + y
return res # use function
value = cal_sum(1,2)

那么如果加上静态类型检测,应该是这么写的:

def cal_sum(x:int, y:int) -> int:
res = x + y
return res # use function
value = cal_sum(1,2)

可以看到,在函数里面的两个参数x,y,已经函数输出后面,都加上int符号,表示函数接受的、输出的都是int类型的。
这也就是一个非常简单的案例,其实在真的大型的项目里面,静态类型可能要比这更加复杂。
虽然写起来复杂了,但是在大型项目里面,结合编辑器IDE的提醒,可以让我们写代码更加丝滑。

鸭子类型
在介绍之前,想问问大家,大家觉得什么什么,可以叫耳机?
    可以发出声音的。
    可以连接手机、电脑的。
    可以戴在头上或者挂在耳朵上的。
好像只要满足上面几点,我们就可以判断这个东西是耳机了。
那么什么叫鸭子类型呢?很简单,就是那些发出嘎嘎嘎叫的小动物,就是鸭子。
说白了,就是我们从功能上定义,只要一个东西,符合某一功能的需求、或者说有对应的行为,那么就可以被判断为一个类型。

在百科上是这么说的:
“鸭子类型”的语言是这么推断的:一只鸟走起来像鸭子、游起泳来像鸭子、叫起来也像鸭子,那它就可以被当做鸭子。也就是说,它不关注对象的类型,而是关注对象具有的行为(方法)
https://www.baike.com/wikiid/7643131612637675304?prd=mobile&view_id=qc73h8mqgxc00

====================================================

protocol

protocol 也可以叫协议,在python3.8开始引入的。可以叫它为static duck typing(静态的鸭子类型)

用起来,也就是和抽象类abc差不多的。说起来挺乏力的,我们这里用一个例子来说。
案例
我们现在有一个案例:
1. 创建一个基础类

我们要创建一个飞人的类型。这个飞人类型将会在我们的未来世界中发挥关键的作用。

from typing import Protocol # line 1

class Flyer(Protocol): # line 2
def fly(self) -> None: # line 3
"""
A flyer can fly
"""
... # line 4

2. 创建超人

在我们未来的世界中,其实有很多超人,比如有会飞的超人,也有会跑的超人。

class FlyingHero:
"""
This hero can fly.
"""
def fly(self): # line 1
... def run(self) ->None:
... class RunningHero:
"""
This hero can run.
"""
def run(self): # line 2
...

1. 注意在FlyingHero里面,也就是在line 1那里,我们给这个超人定义了fly功能。

2. 在RunningHero里面,也就是在line 2那里,这个超人,只能跑。没有fly哦。

3. 定义世界

在这里,我们定义一个世界。

class World:
"""An word that doesn't do anything.""" def make_fly(self, obj:Flyer) -> None: # line 1
return obj.fly()

def main()-> None:
world= World()
world.make_fly(FlyingHero()) # line 1
world.make_fly(RunningHero()) # line 2 if __name__ =='__main__':
main()

那么也都猜出来了,下面代码其实line 1运行其实是没问题的,但是line 2是有问题的.

上面编辑器使用的是vscode,内置的插件Pylance提醒:RunningHero()的类型不符合obj要求的Flyer类型。

4. 发现
你仔细看代码,发现,FlyingHero()都没有基于Flyer类做继承,但是竟然通过了类型检查。
只是因为实现了相同的功能罢了:也就是都实现了Fly功能(或者叫行为)。

5. 进一步的
问一问自己,难道我使用继承不行么?
使用继承也可以解决这种类型检查的问题。
问的好,但是这个已经有答案了。
可以这么回答:
使用abc做一个抽象虚拟类,然后继承,当然也可以做到。但是使用protocol就不需要再做什么继承了。代码变简单了。
在使用第三方的包的时候,不需要再去考虑如何对第三方的一些类做继承,因为使用protocol知识只是检查行为是否相同,而不看别的内容。只要行为(或者叫methods)相同,那就通过类型检查。更简洁。

阅读更多
本来面向对象就已经够复杂了,还以为继承就是面向对象的一个非常牛的设计模式,结果现在有人对我说不用继承就可以实现类似的功能,我就很糊涂了。

那么如果你对继承真的非常熟悉,可以看看这个大哥的回答:
https://www.zhihu.com/question/547885140/answer/2625580341

这个大哥基于一个游戏设计的案例,介绍了在面向对象的时候,使用继承有多麻烦。

大致原因就是:本来使用继承就是为了方便复用,但是现实是不断的修改父类,导致子类在使用的过程中,会出现很多莫名其妙的情况。在这过程中,继承带来的优点就会被淹没。

其实我在学习的rust的时候,发现rust在做oop的时候,就是基于基础的数据结构和若干的方法组合在一起的。当时没感觉出来,但是后面看了越来越多的代码之后,恍然大悟。

===============================================

【转载】 python鸭子类型与protocol的更多相关文章

  1. python 鸭子类型

    首先Python不支持多态,也不用支持多态,python是一种多态语言,崇尚鸭子类型. 在程序设计中,鸭子类型(英语:duck typing)是动态类型的一种风格.在这种风格中,一个对象有效的语义,不 ...

  2. python鸭子类型

    “当看到一只鸟走起来像鸭子.游泳起来像鸭子.叫起来也像鸭子,那么这只鸟就能够被称为鸭子” python的鸭子类型的设计让python的诸多对象的分类和应用更加灵活,需要注意类型和对象的区别(pytho ...

  3. Python鸭子类型思想

    动态语言中经常提到鸭子类型,所谓鸭子类型就是:如果走起路来像鸭子,叫起来也像鸭子,那么它就是鸭子(If it walks like a duck and quacks like a duck, it ...

  4. python鸭子类型(duck type)

    1.什么是鸭子类型顾名思义,就是看起来像鸭子的类型,就可以叫做鸭子类型所以,鸭子类型是一种不严格的类型,弱类型有相同方法的类型,可以归为一类鸭子.2.鸭子类型示例 class dog: def run ...

  5. python之鸭子类型

    python不支持多态,也不用支持多态,python是一种多态语言,崇尚鸭子类型. 在程序设计中,鸭子类型是动态类型的一种风格,不是由继承特定的类或实现特定的接口,而是当前的方法和属性的集合决定,鸭子 ...

  6. python之类的多态(鸭子类型 )、封装和内置函数property

    一.多态 1.什么是多态:一个类表现出的多种状态--->通过继承来实现的例如:class Animal:passclass Dog(Animal):passclass Cat(Animal):p ...

  7. python 全栈开发,Day21(抽象类,接口类,多态,鸭子类型)

    一.昨日复习 派生方法和派生属性 super 只有在子父类拥有同名方法的时候, 想使用子类的对象调用父类的方法时,才使用super super在类内 : super().方法名(arg1,..) 指名 ...

  8. [py]python多态-动态语言的鸭子类型

    弱类型?强类型?动态语言,静态语言 弱类型: 在程序运行过程中,类型可变 还有一种说法: 动态 variables must necessarily be defined before they ar ...

  9. python多态和鸭子类型

    多态与多态性 多态指的是一类事物有多种形态,(一个抽象类有多个子类,因而多态的概念依赖于继承). 比如:文件分为文本文件,可执行文件(在定义角度) 比如 我们按下 F1 键这个动作: 如果当前在 Fl ...

  10. Python多态、鸭子类型

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

随机推荐

  1. Java格式化手机号和身份证号,中间使用星号*隐藏

    Java格式化手机号和身份证号,中间使用星号*隐藏 package com.example.core.mydemo.java; /** * renterMobile=111****1198 * idN ...

  2. DELL服务器安装racadm检测服务器硬件状态

    1.下载racadm命令 For Linux 7及以上版本: https://dl.dell.com/FOLDER07423496M/1/DellEMC-iDRACTools-Web-LX-10.1. ...

  3. EasyExcel 无法读取图片?用poi写了一个工具类

    在平时的开发中,经常要开发 Excel 的导入导出功能.一般使用 poi 或者 EasyExcel 开发,使用 poi 做 excel 比较复杂,大部分开发都会使用 EasyExcel 因为一行代码就 ...

  4. ComfyUI进阶篇:ControlNet核心节点

    前言: ControlNet_aux库包含大量的图片预处理节点,功能丰富,适用于图像分割.边缘检测.姿势检测.深度图处理等多种预处理方式.掌握这些节点的使用是利用ControlNet的关键,本篇文章将 ...

  5. 【JavaScript】js中的浅拷贝与深拷贝与手写实现

    前言 什么是深拷贝与浅拷贝?深拷贝与浅拷贝是js中处理对象或数据复制操作的两种方式.‌在聊深浅拷贝之前咱得了解一下js中的两种数据类型: 基本数据类型(6种) String.Number.Object ...

  6. 4. 系统I/O

    系统 I/O 示例代码: #include <iostream> // 标准库头文件 // #include "myheader.h" // 自己写的头文件 void ...

  7. WebGL加载本地模型

    前言 大部分的webgl框架,比如threejs和babylon等,都可以加载obj和gltf模型. 我们的引擎,基于three封装,同样有加载模型的loader,因此加载obj和gltf模型也是很简 ...

  8. Visual Studio 必备插件集合:AI 助力开发

     一.前言 2024年AI浪潮席卷全球,编程界迎来全新的挑战与机遇.智能编程.自动化测试.代码审查,这一切都得益于AI技术的迅猛发展,它正在重塑开发者的日常,让编写代码变得更加高效.智能. 精选出最受 ...

  9. ABC347

    A link 很简单 遍历,判断模\(k\)是否为\(0\),如果为\(0\),输出\(a_i/k\). 点击查看代码 #include<bits/stdc++.h> using name ...

  10. Python版RNA-seq分析教程:差异表达基因分析

    Bulk RNA-seq 分析的一个重要任务是分析差异表达基因,我们可以用 omicverse包来完成这个任务.对于差异表达分析而言,首先,我们可> 以先将 gene_id 改为 gene_na ...