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 相关文章推荐
浅谈MySQL中的触发器
May 05 Python
通过mod_python配置运行在Apache上的Django框架
Jul 22 Python
在Python中的Django框架中进行字符串翻译
Jul 27 Python
Python实现按照指定要求逆序输出一个数字的方法
Apr 19 Python
python实现输入数字的连续加减方法
Jun 22 Python
python 获取图片分辨率的方法
Jan 08 Python
Python 实现文件打包、上传与校验的方法
Feb 13 Python
python定位xpath 节点位置的方法
Aug 27 Python
python创建n行m列数组示例
Dec 02 Python
opencv resize图片为正方形尺寸的实现方法
Dec 26 Python
OpenCV利用python来实现图像的直方图均衡化
Oct 21 Python
python如何正确使用yield
May 21 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
第1次亲密接触PHP5(2)
2006/10/09 PHP
在php中取得image按钮传递的name值
2006/10/09 PHP
php导出生成word的方法
2015/12/25 PHP
PHP验证码类ValidateCode解析
2017/01/07 PHP
php 实现银联商务H5支付的示例代码
2019/10/12 PHP
laravel框架使用FormRequest进行表单验证,验证异常返回JSON操作示例
2020/02/18 PHP
JS获取IUSR_机器名和IWAM_机器名帐号的密码
2006/12/06 Javascript
JS 控制非法字符的输入代码
2009/12/04 Javascript
js模拟类继承小例子
2010/07/17 Javascript
javascript预览上传图片发现的问题的解决方法
2010/11/25 Javascript
css transform 3D幻灯片特效实现步骤解读
2013/03/27 Javascript
jquery实现翻动fadeIn显示的方法
2015/03/05 Javascript
JavaScript中两个字符串的匹配
2016/06/08 Javascript
用iframe实现不刷新整个页面上传图片的实例
2016/11/18 Javascript
Angular中点击li标签实现更改颜色的核心代码
2017/12/08 Javascript
微信小程序版翻牌小游戏
2018/01/26 Javascript
Node.js利用console输出日志文件的方法示例
2018/04/27 Javascript
快速解决处理后台返回json数据格式的问题
2018/08/07 Javascript
微信小程序仿今日头条导航栏滚动解析
2019/08/20 Javascript
[02:40]2014DOTA2 国际邀请赛中国区预选赛 四大豪门抵达华西村
2014/05/23 DOTA
手动实现把python项目发布为exe可执行程序过程分享
2014/10/23 Python
python开发环境PyScripter中文乱码问题解决方案
2016/09/11 Python
基于python代码批量处理图片resize
2020/06/04 Python
keras 多任务多loss实例
2020/06/22 Python
python转化excel数字日期为标准日期操作
2020/07/14 Python
python中常用的数据结构介绍
2021/01/12 Python
css3绘制天猫logo实现代码
2012/11/06 HTML / CSS
LN-CC美国:伦敦时尚生活的缩影
2019/02/19 全球购物
日本最大化妆品和美容产品的综合口碑网站:cosme shopping
2019/08/28 全球购物
枚举和一组预处理的#define有什么不同
2016/09/21 面试题
JAVA招聘远程笔试题
2015/07/23 面试题
供货协议书
2014/04/22 职场文书
实习报告评语
2014/04/26 职场文书
学术会议领导致辞
2015/07/29 职场文书
pandas时间序列之pd.to_datetime()的实现
2022/06/16 Python
Android基础入门之dataBinding的简单使用教程
2022/06/21 Java/Android