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内置数据类型详解
Aug 18 Python
Python解决鸡兔同笼问题的方法
Dec 20 Python
Python实现基本线性数据结构
Aug 22 Python
对python的文件内注释 help注释方法
May 23 Python
Python3实现的反转单链表算法示例
Mar 08 Python
Python绘制堆叠柱状图的实例
Jul 09 Python
django admin.py 外键,反向查询的实例
Jul 26 Python
python单向循环链表原理与实现方法示例
Dec 03 Python
pytorch 查看cuda 版本方式
Jun 23 Python
python实现感知机模型的示例
Sep 30 Python
python爬取招聘要求等信息实例
Nov 20 Python
详细介绍python类及类的用法
May 31 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支持断点续传的源码
2010/05/16 PHP
php设计模式 DAO(数据访问对象模式)
2011/06/26 PHP
PHP实现对png图像进行缩放的方法(支持透明背景)
2015/07/15 PHP
YII框架行为behaviors用法示例
2019/04/26 PHP
关于div自适应高度/左右高度自适应一致的js代码
2013/03/22 Javascript
javascript实现信息的显示和隐藏如注册页面
2013/12/03 Javascript
javascript绘制漂亮的心型线效果完整实例
2016/02/02 Javascript
使用Ajax与服务器(JSON)通信实例
2016/11/04 Javascript
jQuery插件HighCharts绘制2D带Label的折线图效果示例【附demo源码下载】
2017/03/08 Javascript
详解vue-loader在项目中是如何配置的
2018/06/04 Javascript
mongodb初始化并使用node.js实现mongodb操作封装方法
2019/04/02 Javascript
ligerUI的ligerDialog关闭刷新的方法
2019/09/27 Javascript
JavaScript React如何修改默认端口号方法详解
2020/07/28 Javascript
动态实现element ui的el-table某列数据不同样式的示例
2021/01/22 Javascript
[02:22]2018DOTA2亚洲邀请赛VG赛前采访
2018/04/03 DOTA
如何使用七牛Python SDK写一个同步脚本及使用教程
2015/08/23 Python
Python实现命令行通讯录实例教程
2016/08/18 Python
python中pandas.DataFrame的简单操作方法(创建、索引、增添与删除)
2017/03/12 Python
Python之os操作方法(详解)
2017/06/15 Python
对python 匹配字符串开头和结尾的方法详解
2018/10/27 Python
解决Pycharm下面出现No R interpreter defined的问题
2018/10/29 Python
python实现网页自动签到功能
2019/01/21 Python
python使用KNN算法识别手写数字
2019/04/25 Python
Python学习笔记之列表推导式实例分析
2019/08/13 Python
Pytorch中的variable, tensor与numpy相互转化的方法
2019/10/10 Python
Html5大文件断点续传实现方法
2015/12/05 HTML / CSS
Origins加拿大官网:雅诗兰黛集团高端植物护肤品牌
2017/11/19 全球购物
Kivari官网:在线购买波西米亚服装
2018/10/29 全球购物
古驰英国官网:GUCCI英国
2020/03/07 全球购物
优秀少先队辅导员先进事迹材料
2014/05/18 职场文书
书法大赛策划方案
2014/06/04 职场文书
2014年学校财务工作总结
2014/12/06 职场文书
小学大队干部竞选稿
2015/11/20 职场文书
MySQL创建索引需要了解的
2021/04/08 MySQL
使用 Apache 反向代理的设置技巧
2022/01/18 Servers
Golang 对es的操作实例
2022/04/20 Golang