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中实现远程调用(RPC、RMI)简单例子
Apr 28 Python
在Python的web框架中中编写日志列表的教程
Apr 30 Python
Saltstack快速入门简单汇总
Mar 01 Python
人脸识别经典算法一 特征脸方法(Eigenface)
Mar 13 Python
Python cookbook(数据结构与算法)同时对数据做转换和换算处理操作示例
Mar 23 Python
python操作mysql代码总结
Jun 01 Python
python分布式编程实现过程解析
Nov 08 Python
Python实现栈和队列的简单操作方法示例
Nov 29 Python
python通过移动端访问查看电脑界面
Jan 06 Python
matplotlib quiver箭图绘制案例
Apr 17 Python
Python3合并两个有序数组代码实例
Aug 11 Python
Python何绘制带有背景色块的折线图
Apr 23 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高级对象构建 多个构造函数的使用
2012/02/05 PHP
数据库中排序的对比及使用条件详解
2012/02/23 PHP
php 对输入信息的进行安全过滤的函数代码
2012/06/29 PHP
基于python发送邮件的乱码问题的解决办法
2013/04/25 PHP
PHP连接MySQL的2种方法小结以及防止乱码
2014/03/11 PHP
php从csv文件读取数据并输出到网页的方法
2015/03/14 PHP
详解WordPress中分类函数wp_list_categories的使用
2016/01/04 PHP
Zend Framework教程之模型Model基本规则和使用方法
2016/03/04 PHP
javascript各浏览器中option元素的表现差异
2011/04/07 Javascript
跨域请求之jQuery的ajax jsonp的使用解惑
2011/10/09 Javascript
JS实现点击文字对应DIV层不停闪动效果的方法
2015/03/02 Javascript
Bootstrap每天必学之警告框插件
2016/04/26 Javascript
用jQuery实现圆点图片轮播效果
2017/03/19 Javascript
jQuery初级教程之网站品牌列表效果
2017/08/02 jQuery
vue实现登陆登出的实现示例
2017/09/15 Javascript
JS实现的汉字与Unicode码相互转化功能分析
2018/05/25 Javascript
对vuejs的v-for遍历、v-bind动态改变值、v-if进行判断的实例讲解
2018/08/27 Javascript
详解vuex状态管理模式
2018/11/01 Javascript
vue3 源码解读之 time slicing的使用方法
2019/10/31 Javascript
Node Mongoose用法详解【Mongoose使用、Schema、对象、model文档等】
2020/05/13 Javascript
[47:43]完美世界DOTA2联赛PWL S3 Magama vs GXR 第二场 12.19
2020/12/24 DOTA
python实现的简单文本类游戏实例
2015/04/28 Python
Python闭包的两个注意事项(推荐)
2017/03/20 Python
基于DataFrame改变列类型的方法
2018/07/25 Python
python 解压、复制、删除 文件的实例代码
2020/02/26 Python
python传到前端的数据,双引号被转义的问题
2020/04/03 Python
收集的22款给力的HTML5和CSS3帮助工具
2012/09/14 HTML / CSS
css3 旋转按钮 使用CSS3创建一个旋转可变色按钮
2012/12/31 HTML / CSS
Spartoo西班牙官网:法国时尚购物网站
2018/03/27 全球购物
一加手机美国官方网站:OnePlus美国
2019/09/19 全球购物
土地转让协议书范本
2014/04/15 职场文书
水电工程师岗位职责
2015/02/13 职场文书
家长通知书家长意见
2015/06/03 职场文书
远程教育培训心得体会
2016/01/09 职场文书
简短的人生哲理(38句)
2019/08/13 职场文书
php访问对象中的成员的实例方法
2021/11/17 PHP