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发送邮件接收邮件示例分享
Jan 21 Python
使用Python的Tornado框架实现一个一对一聊天的程序
Apr 25 Python
使用Python编写基于DHT协议的BT资源爬虫
Mar 19 Python
pycharm+django创建一个搜索网页实例代码
Jan 24 Python
详解用python写网络爬虫-爬取新浪微博评论
May 10 Python
Django 实现前端图片压缩功能的方法
Aug 07 Python
flask/django 动态查询表结构相同表名不同数据的Model实现方法
Aug 29 Python
python json.dumps() json.dump()的区别详解
Jul 14 Python
Python模块常用四种安装方式
Oct 20 Python
Python实现FTP文件定时自动下载的步骤
Dec 19 Python
[原创]赚疯了!转手立赚800+?大佬的python「抢茅台脚本」使用教程
Jan 12 Python
python3 sqlite3限制条件查询的操作
Apr 07 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
受疫情影响 动画《Re从零开始的异世界生活》第二季延期至7月
2020/03/10 日漫
php 破解防盗链图片函数
2008/12/09 PHP
PHP图片处理类 phpThumb参数用法介绍
2012/03/11 PHP
PHP转换IP地址到真实地址的方法详解
2013/06/09 PHP
详解php魔术方法(Magic methods)的使用方法
2016/02/14 PHP
[原创]php简单防盗链验证实现方法
2016/07/09 PHP
jquery formValidator插件ajax验证 内容不做任何修改再离开提示错误的bug解决方法
2013/01/04 Javascript
Jquery $.getJSON 在IE下的缓存问题解决方法
2014/10/10 Javascript
使用npm发布Node.JS程序包教程
2015/03/02 Javascript
Windows下Node.js安装及环境配置方法
2017/09/18 Javascript
Vue v2.4中新增的$attrs及$listeners属性使用教程
2018/01/08 Javascript
BootStrap自定义popover,点击区域隐藏功能的实现
2018/01/23 Javascript
js获取html页面代码中图片地址的实现代码
2018/03/05 Javascript
vue脚手架及vue-router基本使用
2018/04/09 Javascript
js实现上传图片并显示图片名称
2019/12/18 Javascript
JavaScript如何实现监听键盘输入和鼠标监点击
2020/07/20 Javascript
在Vue中使用Select选择器拼接label的操作
2020/10/22 Javascript
[01:39:42]Fnatic vs Mineski 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
Python3实现生成随机密码的方法
2014/08/23 Python
使用Python脚本实现批量网站存活检测遇到问题及解决方法
2016/10/11 Python
老生常谈Python序列化和反序列化
2017/06/28 Python
python3+dlib实现人脸识别和情绪分析
2018/04/21 Python
python寻找list中最大值、最小值并返回其所在位置的方法
2018/06/27 Python
浅谈django orm 优化
2018/08/18 Python
Django框架搭建的简易图书信息网站案例
2019/05/25 Python
Python登录系统界面实现详解
2019/06/25 Python
python中如何实现将数据分成训练集与测试集的方法
2019/09/13 Python
Python基于paramunittest模块实现excl参数化
2020/04/26 Python
Python爬虫爬取百度搜索内容代码实例
2020/06/05 Python
PyCharm 2020.2 安装详细教程
2020/09/25 Python
意大利在线高尔夫商店:Online Golf
2021/03/09 全球购物
.NET remoting的两种通道是什么
2016/05/31 面试题
公司承诺书范文
2014/05/19 职场文书
2015年度工程师评职称工作总结
2015/10/14 职场文书
Java elasticsearch安装以及部署教程
2021/06/28 Java/Android
SQL Server数据库查询出现阻塞之性能调优
2022/04/10 SQL Server