Python 中的单分派泛函数你真的了解吗


Posted in Python onJune 22, 2021

泛型,如果你学过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 相关文章推荐
自己编程中遇到的Python错误和解决方法汇总整理
Jun 03 Python
python发送HTTP请求的方法小结
Jul 08 Python
Python实现通过文件路径获取文件hash值的方法
Apr 29 Python
linux环境下的python安装过程图解(含setuptools)
Nov 22 Python
python的pygal模块绘制反正切函数图像方法
Jul 16 Python
python用win32gui遍历窗口并设置窗口位置的方法
Jul 26 Python
python如果快速判断数字奇数偶数
Nov 13 Python
浅谈Python访问MySQL的正确姿势
Jan 07 Python
快速了解Python开发环境Spyder
Jun 29 Python
python如何操作mysql
Aug 17 Python
python 获取计算机的网卡信息
Feb 18 Python
Python基础之数据结构详解
Apr 28 Python
Python实现DBSCAN聚类算法并样例测试
python中sqllite插入numpy数组到数据库的实现方法
Jun 21 #Python
利用Python第三方库实现预测NBA比赛结果
Django实现drf搜索过滤和排序过滤
python生成可执行exe控制Microsip自动填写号码并拨打功能
详解Python自动化之文件自动化处理
Jun 21 #Python
Python Pandas pandas.read_sql_query函数实例用法分析
Jun 21 #Python
You might like
PHP 上传文件的方法(类)
2009/07/30 PHP
php函数的常用方法及注意之处小结
2011/07/10 PHP
js DOM 元素ID就是全局变量
2012/09/20 Javascript
在js(jquery)中获得文本框焦点和失去焦点的方法
2012/12/04 Javascript
使用纯javascript实现放大镜效果
2015/03/18 Javascript
javascript中callee与caller的区别分析
2015/04/20 Javascript
基于javascript实现listbox左右移动
2016/01/29 Javascript
js获取Html元素的实际宽度高度的方法
2016/05/19 Javascript
jquery ajax后台返回list,前台用jquery遍历list的实现
2016/10/30 Javascript
bootstrap suggest下拉框使用详解
2017/04/10 Javascript
js-FCC算法-No repeats please字符串的全排列(详解)
2017/05/02 Javascript
浅谈 Vue v-model指令的实现原理
2017/06/08 Javascript
js中url对象化管理分析
2017/12/29 Javascript
Vue 组件参数校验与非props特性的方法
2019/02/12 Javascript
jquery向后台提交数组的代码分析
2020/02/20 jQuery
ES6 Symbol在对象中的作用实例分析
2020/06/06 Javascript
[06:30]DOTA2英雄梦之声_第15期_死亡先知
2014/06/21 DOTA
[36:19]2018DOTA2亚洲邀请赛 小组赛 A组加赛 Newbee vs LGD
2018/04/03 DOTA
[01:54]TI珍贵瞬间系列(五):压力
2020/08/29 DOTA
[01:02:32]DOTA2-DPC中国联赛 正赛 iG vs PSG.LGD BO3 第二场 2月26日
2021/03/11 DOTA
Python multiprocessing.Manager介绍和实例(进程间共享数据)
2014/11/21 Python
python中实现指定时间调用函数示例代码
2017/09/08 Python
从请求到响应过程中django都做了哪些处理
2018/08/01 Python
通过Turtle库在Python中绘制一个鼠年福鼠
2020/02/03 Python
将数据集制作成VOC数据集格式的实例
2020/02/17 Python
I.T集团香港官方商城:ITeSHOP.com Hong Kong
2019/02/15 全球购物
亚洲颇具影响力的男性在线购物零售商:His
2019/11/24 全球购物
毕业自我鉴定书
2014/03/24 职场文书
员工安全责任书范本
2014/07/24 职场文书
暑期培训班策划方案
2014/08/26 职场文书
文化大革命观后感
2015/06/17 职场文书
关于职业道德的心得体会
2016/01/18 职场文书
变长双向rnn的正确使用姿势教学
2021/05/31 Python
使用Djongo模块在Django中使用MongoDB数据库
2021/06/20 Python
MySQL子查询中order by不生效问题的解决方法
2021/08/02 MySQL
python中的3种定义类方法
2021/11/27 Python