【转载】 python鸭子类型与protocol
版权声明:本文为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的更多相关文章
- python 鸭子类型
首先Python不支持多态,也不用支持多态,python是一种多态语言,崇尚鸭子类型. 在程序设计中,鸭子类型(英语:duck typing)是动态类型的一种风格.在这种风格中,一个对象有效的语义,不 ...
- python鸭子类型
“当看到一只鸟走起来像鸭子.游泳起来像鸭子.叫起来也像鸭子,那么这只鸟就能够被称为鸭子” python的鸭子类型的设计让python的诸多对象的分类和应用更加灵活,需要注意类型和对象的区别(pytho ...
- Python鸭子类型思想
动态语言中经常提到鸭子类型,所谓鸭子类型就是:如果走起路来像鸭子,叫起来也像鸭子,那么它就是鸭子(If it walks like a duck and quacks like a duck, it ...
- python鸭子类型(duck type)
1.什么是鸭子类型顾名思义,就是看起来像鸭子的类型,就可以叫做鸭子类型所以,鸭子类型是一种不严格的类型,弱类型有相同方法的类型,可以归为一类鸭子.2.鸭子类型示例 class dog: def run ...
- python之鸭子类型
python不支持多态,也不用支持多态,python是一种多态语言,崇尚鸭子类型. 在程序设计中,鸭子类型是动态类型的一种风格,不是由继承特定的类或实现特定的接口,而是当前的方法和属性的集合决定,鸭子 ...
- python之类的多态(鸭子类型 )、封装和内置函数property
一.多态 1.什么是多态:一个类表现出的多种状态--->通过继承来实现的例如:class Animal:passclass Dog(Animal):passclass Cat(Animal):p ...
- python 全栈开发,Day21(抽象类,接口类,多态,鸭子类型)
一.昨日复习 派生方法和派生属性 super 只有在子父类拥有同名方法的时候, 想使用子类的对象调用父类的方法时,才使用super super在类内 : super().方法名(arg1,..) 指名 ...
- [py]python多态-动态语言的鸭子类型
弱类型?强类型?动态语言,静态语言 弱类型: 在程序运行过程中,类型可变 还有一种说法: 动态 variables must necessarily be defined before they ar ...
- python多态和鸭子类型
多态与多态性 多态指的是一类事物有多种形态,(一个抽象类有多个子类,因而多态的概念依赖于继承). 比如:文件分为文本文件,可执行文件(在定义角度) 比如 我们按下 F1 键这个动作: 如果当前在 Fl ...
- Python多态、鸭子类型
一.多态 多态指的是一类事物有多种形态. 动物有多种形态:人,狗,猪 import abc class Animal(metaclass=abc.ABCMeta): #同一类事物:动物 @abc.ab ...
随机推荐
- 前端开发环境配置 nvm | npm 镜像 | git
安装 nvm nvm 是一个node版本管理工具,它可以让我们安装多个node版本并在需要的时候切换 # nvm 下载地址 https://github.com/coreybutler/nvm-win ...
- vite+vue3+ts+elementPlus前端框架搭建 [三] router路由管理
路由包括动态路由.静态路由两种,本文中以静态路由的方式实现了动态路由. 1. 创建Router 在Src目录下创建router文件夹,并在router文件夹下创建index.ts文件. index.t ...
- webpack-bundle-analyzer 分析打包模块大小优化
安装 webpack-bundle-analyzer npm i webpack-bundle-analyzer -D 配置vue.config.js module.exports = defineC ...
- RAS非对称加解密-RAS加解密和签名和验签,密钥生成器(java代码)
RAS非对称加解密-RAS加解密和签名和验签,密钥生成器(java代码)RSA 算法是一种非对称加解密算法.服务方生成一对 RSA 密钥,即公钥 + 私钥,将公钥提供给调用方,调用方使用公钥对数据进行 ...
- RIP总结
RIP 两种更新方式:定期更新和触发更新 管理距离为120,更新使用UDP520,更新周期30s,使用跳数作为度量值,最大15 RIP有三个版本RIPv1,RIPv2,RIPn ...
- 算法金 | 决策树、随机森林、bagging、boosting、Adaboost、GBDT、XGBoost 算法大全
大侠幸会,在下全网同名「算法金」 0 基础转 AI 上岸,多个算法赛 Top 「日更万日,让更多人享受智能乐趣」 决策树是一种简单直观的机器学习算法,它广泛应用于分类和回归问题中.它的核心思想是将复杂 ...
- 【深度学习 有效炼丹】多GPU使用教程, DP与DDP对比, ray多线程并行处理等 [GPU利用率低的分析]
️ 前言 更新日志: 20220404:新增一个DDP 加载模型时显存分布不均问题,见目录遇到的问题及解决处 主要是上次server12 被自己一个train 直接线程全部拉满了(没错 ... ser ...
- 2个qubit的量子门
量子计算机就是基于单qubit门和双qubit门的,再多的量子操作都是基于这两种门.双qubit门比单qubit门难理解得多,不过也重要得多.它可以用来创建纠缠,没有纠缠,量子机就不可能有量子霸权. ...
- Redis常见的16个使用场景
1.缓存 String类型 例如:热点数据缓存(例如报表.明星出轨),对象缓存.全页缓存.可以提升热点数据的访问数据. 2.数据共享分布式 String 类型,因为 Redis 是分布式的独立服务,可 ...
- MySQL与Redis数据双写一致性工程落地案例
复习-面试题 多个线程同时去查询数据库的这条数据,那么我们可以在第一个查询数据的请求上使用一个 互斥锁来锁住它. 其他的线程走到这一步拿不到锁就等着,等第一个线程查询到了数据,然后做缓存. 后面的线程 ...