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时间戳与时间字符串互相转换实例代码
Nov 28 Python
python脚本实现分析dns日志并对受访域名排行
Sep 18 Python
深入讲解Java编程中类的生命周期
Feb 05 Python
如何在Python函数执行前后增加额外的行为
Oct 20 Python
Python中的连接符(+、+=)示例详解
Jan 13 Python
python 设置文件编码格式的实现方法
Dec 21 Python
Python IDLE清空窗口的实例
Jun 25 Python
Django中间件基础用法详解
Jul 18 Python
Django框架获取form表单数据方式总结
Apr 22 Python
django 模型中的计算字段实例
May 19 Python
3分钟看懂Python后端必须知道的Django的信号机制
Jul 26 Python
python实现的web监控系统
Apr 27 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执行速度全攻略(下)
2006/10/09 PHP
php模拟socket一次连接,多次发送数据的实现代码
2011/07/26 PHP
php 判断页面或图片是否经过gzip压缩的方法
2017/04/05 PHP
基于mouseout和mouseover等类似事件的冒泡问题解决方法
2013/11/18 Javascript
抛弃Nginx使用nodejs做反向代理服务器
2014/07/17 NodeJs
JQuery 实现在同一页面锚点链接之间的平滑滚动
2014/10/29 Javascript
JS实现简单的键盘打字的效果
2015/04/24 Javascript
jQuery插件scroll实现无缝滚动效果
2015/04/27 Javascript
jQuery的Scrollify插件实现滑动到页面下一节点
2015/07/05 Javascript
javascript常用的方法整理
2015/08/20 Javascript
JS实现黑客帝国文字下落效果
2015/09/01 Javascript
jQuery实现点击水纹波动动画
2016/04/10 Javascript
Js+Ajax,Get和Post在使用上的区别小结
2016/06/08 Javascript
JavaScript DOM 对象深入了解
2016/07/20 Javascript
AngularJS入门教程之数据绑定原理详解
2016/11/02 Javascript
js实现倒计时及时间对象
2016/11/15 Javascript
js前端实现多图图片上传预览的两个方法(推荐)
2016/11/18 Javascript
js实现登录框鼠标拖拽效果
2017/03/09 Javascript
ES6中Iterator与for..of..遍历用法分析
2017/03/31 Javascript
vue+element使用动态加载路由方式实现三级菜单页面显示的操作
2020/08/04 Javascript
vuex Module将 store 分割成模块的操作
2020/12/07 Vue.js
vue 使用 v-model 双向绑定父子组件的值遇见的问题及解决方案
2021/03/01 Vue.js
[40:53]完美世界DOTA2联赛PWL S3 Magma vs DLG 第二场 12.18
2020/12/20 DOTA
python使用Berkeley DB数据库实例
2014/09/26 Python
深度定制Python的Flask框架开发环境的一些技巧总结
2016/07/12 Python
python实现二叉树的遍历
2017/12/11 Python
pandas对指定列进行填充的方法
2018/04/11 Python
如何使用Python实现斐波那契数列
2019/07/02 Python
Python能做什么
2020/06/02 Python
html5中localStorage本地存储的简单使用
2017/06/16 HTML / CSS
Html5实现用户注册自动校验功能实例代码
2016/05/24 HTML / CSS
Html5实现文件异步上传功能
2017/05/19 HTML / CSS
Gibson London官网:以地道的英国男装而著称
2019/12/06 全球购物
教育专业个人求职信
2013/12/02 职场文书
超市员工辞职信范文
2015/05/12 职场文书
初三化学教学反思
2016/02/22 职场文书