Python 里的「单分派泛函数」到底是什么?
泛型,如果你学过Java ,应该对它不陌生吧。但你可能不知道在 Python 中(3.4+ ),也可以实现简单的泛型函数。
在Python中只能实现基于单个(第一个)参数的数据类型来选择具体的实现方式,官方名称 是 single-dispatch。你或许听不懂,说简单点,就是可以实现第一个参数的数据类型不同,其调用的函数也就不同。
singledispatch 是 PEP443 中引入的,如果你对此有兴趣,PEP443 应该是最好的学习文档:
https://www.python.org/dev/peps/pep-0443/
A generic function is composed of multiple functions implementing the same operation for different types. Which implementation should be used during a call is determined by the dispatch algorithm. When the implementation is chosen based on the type of a single argument, this is known as single dispatch.
它使用方法极其简单,只要被singledispatch 装饰的函数,就是一个单分派的(single-dispatch )的泛函数(generic functions)。
单分派:根据一个参数的类型,以不同方式执行相同的操作的行为。
多分派:可根据多个参数的类型选择专门的函数的行为。
泛函数:多个函数绑在一起组合成一个泛函数。
这边举个简单的例子,介绍一下使用方法
from functools import singledispatch
@singledispatch
def age(obj):
print('请传入合法类型的参数!')
@age.register(int)
def _(age):
print('我已经{}岁了。'.format(age))
@age.register(str)
def _(age):
print('I am {} years old.'.format(age))
age(23) # int
age('twenty three') # str
age(['23']) # list
执行结果
我已经23岁了。
I am twenty three years old.
请传入合法类型的参数!
说起泛型,其实在 Python 本身的一些内建函数中并不少见,比如 len() , iter(),copy.copy() ,pprint() 等
你可能会问,它有什么用呢?实际上真没什么用,你不用它或者不认识它也完全不影响你编码。
我这里举个例子,你可以感受一下。
大家都知道,Python 中有许许多的数据类型,比如 str,list, dict, tuple 等,不同数据类型的拼接方式各不相同,所以我这里我写了一个通用的函数,可以根据对应的数据类型对选择对应的拼接方式拼接,而且不同数据类型我还应该提示无法拼接。以下是简单的实现。
def check_type(func):
def wrapper(*args):
arg1, arg2 = args[:2]
if type(arg1) != type(arg2):
return '【错误】:参数类型不同,无法拼接!!'
return func(*args)
return wrapper
@singledispatch
def add(obj, new_obj):
raise TypeError
@add.register(str)
@check_type
def _(obj, new_obj):
obj += new_obj
return obj
@add.register(list)
@check_type
def _(obj, new_obj):
obj.extend(new_obj)
return obj
@add.register(dict)
@check_type
def _(obj, new_obj):
obj.update(new_obj)
return obj
@add.register(tuple)
@check_type
def _(obj, new_obj):
return (*obj, *new_obj)
print(add('hello',', world'))
print(add([1,2,3], [4,5,6]))
print(add({'name': 'wangbm'}, {'age':25}))
print(add(('apple', 'huawei'), ('vivo', 'oppo')))
# list 和 字符串 无法拼接
print(add([1,2,3], '4,5,6'))
输出结果如下
hello, world
[1, 2, 3, 4, 5, 6]
{'name': 'wangbm', 'age': 25}
('apple', 'huawei', 'vivo', 'oppo')
【错误】:参数类型不同,无法拼接!!
如果不使用singledispatch 的话,你可能会写出这样的代码。
def check_type(func):
def wrapper(*args):
arg1, arg2 = args[:2]
if type(arg1) != type(arg2):
return '【错误】:参数类型不同,无法拼接!!'
return func(*args)
return wrapper
@check_type
def add(obj, new_obj):
if isinstance(obj, str) :
obj += new_obj
return obj
if isinstance(obj, list) :
obj.extend(new_obj)
return obj
if isinstance(obj, dict) :
obj.update(new_obj)
return obj
if isinstance(obj, tuple) :
return (*obj, *new_obj)
print(add('hello',', world'))
print(add([1,2,3], [4,5,6]))
print(add({'name': 'wangbm'}, {'age':25}))
print(add(('apple', 'huawei'), ('vivo', 'oppo')))
# list 和 字符串 无法拼接
print(add([1,2,3], '4,5,6'))
输出如下
hello, world
[1, 2, 3, 4, 5, 6]
{'name': 'wangbm', 'age': 25}
('apple', 'huawei', 'vivo', 'oppo')
【错误】:参数类型不同,无法拼接!!
以上是我个人的一些理解,如有误解误传,还请你后台留言帮忙指正!

Python 里的「单分派泛函数」到底是什么?的更多相关文章
- 教你用python搭建一个「生活常识解答」机器人
今天教大家如何用Python爬虫去搭建一个「生活常识解答」机器人. 思路:这个机器人主要是依托于"阿里达摩院发布的语言模型PLUG",通过爬虫的方式,发送post请求(提问),然后 ...
- Linux 小知识翻译 - 「单CD 的linux」
这次聊聊「单CD Linux」. 所谓「单CD Linux」,就是不用安装,从CD-ROM启动后就可以使用的Linux. 有名的KNOPPIX就是「单CD Linux」,此外还有Puppy Linux ...
- 「每日一题」有人上次在dy面试,面试官问我:vue数据绑定的实现原理。你说我该如何回答?
关注「松宝写代码」,精选好文,每日一题 时间永远是自己的 每分每秒也都是为自己的将来铺垫和增值 作者:saucxs | songEagle 来源:原创 一.前言 文章首发在「松宝写代码」 2020. ...
- Python里的单下划线,双下划线,以及前后都带下划线的意义
Python里的单下划线,双下划线,以及前后都带下划线的意义: 单下划线如:_name 意思是:不能通过from modules import * 导入,如需导入需要:from modules imp ...
- Python(三)基础篇之「模块&面向对象编程」
[笔记]Python(三)基础篇之「模块&面向对象编程」 2016-12-07 ZOE 编程之魅 Python Notes: ★ 如果你是第一次阅读,推荐先浏览:[重要公告]文章更新. ...
- 「查缺补漏」巩固你的Redis知识体系
Windows Redis 安装 链接: https://pan.baidu.com/s/1MJnzX_qRuNXJI09euzkPGA 提取码: 2c6w 复制这段内容后打开百度网盘手机App,操作 ...
- 「洛谷 P1801」黑匣子
好像很久没有更过博客了,因为博主这几周很忙.其实是在搞颓. 题意很难懂,所以就不重复了.其实是懒. 一眼看上去这是个 \(Splay\) 裸题,直接插入一个数,查询区间第 \(K\) 大,但是这样太不 ...
- [转帖]「知乎知识库」— 5G
「知乎知识库」— 5G 甜草莓 https://zhuanlan.zhihu.com/p/55998832 通信 话题的优秀回答者 已关注 881 人赞同了该文章 谢 知识库 邀请~本文章是几个答 ...
- 从0开始学习 GitHub 系列之「03.Git 速成」
前面的 GitHub 系列文章介绍过,GitHub 是基于 Git 的,所以也就意味着 Git 是基础,如果你不会 Git ,那么接下来你完全继续不下去,所以今天的教程就来说说 Git ,当然关于 G ...
随机推荐
- linux 搜索某个系统命令的位置
Which命令 功能简述which命令的作用是在PATH变量指定的路径中搜索某个系统命令的位置并且返回第一个搜索结果.也就是说使用which命令就可以看到某个系统命令是否存在以及执行的到底是哪一个位置 ...
- python的知识统计笔记
python的发展
- nginx日志模块及日志定时切割
一:作用 Ngx_http_log_module:定义日志格式,并且以指定的格式保存. 二:示例配置 log_format compression '$remote_addr - $remote_us ...
- go语言调度器源代码情景分析之四:函数调用栈
本文是<go调度器源代码情景分析>系列 第一章 预备知识的第3小节. 什么是栈 栈是一种“后进先出”的数据结构,它相当于一个容器,当需要往容器里面添加元素时只能放在最上面的一个元素之上,需 ...
- RabbitMQ 消息队列 入门 第二章(交换类型fanout)
1.安装完 RabbitMQ 之后,我们可以点击 http://localhost:15672/#/ 默认账号:guest 密码: guest 在这上面我们可以查看执行情况.管理连接.管理队列 ...
- 【原】javascript笔记之this用法
javascript中的this学习起来相对复杂,最近花了点时间研究,总结起来大概这只有5种情况,相信只要熟悉这5种用法,基本是可以解决所有的this问题,文本不介绍this设计原理,只介绍用法,阅读 ...
- RabbitMQ死信队列另类用法之复合死信
前言 在业务开发过程中,我们常常需要做一些定时任务,这些任务一般用来做监控或者清理任务,比如在订单的业务场景中,用户在创建订单后一段时间内,没有完成支付,系统将自动取消该订单,并将库存返回到商品中,又 ...
- ubuntu中使用docker部署.netcore2.1
概述 .netcore发布这么久,到现在才在项目中实际运用,之前算是了解一点,一般找工作都会问是否运用过.netcore,软件研发来说,如果这个技术没用过,觉得挺难,其实不难..netcore ...
- 适配器模式(Adapter Pattern)
适配器模式概述 定义:将一个类的接口转化成客户希望的另一个接口,适配器模式让那些接口不兼容的类可以一起工作.别名(包装器[Wrapper]模式) 它属于创建型模式的成员,何为创建型模式:就是关注如何将 ...
- 《深入理解Java虚拟机》读书笔记(第三章)
垃圾收集器与内存分配策略(第三章) 前言,众所周知,Java是由c++进化而来,c++在内存需自己申请,自己释放,于是就有了Java的动态内存分配.书的第三章开篇,有这样一句话描述的很妙——Java与 ...