泛型,如果你学过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 里的「单分派泛函数」到底是什么?的更多相关文章

  1. 教你用python搭建一个「生活常识解答」机器人

    今天教大家如何用Python爬虫去搭建一个「生活常识解答」机器人. 思路:这个机器人主要是依托于"阿里达摩院发布的语言模型PLUG",通过爬虫的方式,发送post请求(提问),然后 ...

  2. Linux 小知识翻译 - 「单CD 的linux」

    这次聊聊「单CD Linux」. 所谓「单CD Linux」,就是不用安装,从CD-ROM启动后就可以使用的Linux. 有名的KNOPPIX就是「单CD Linux」,此外还有Puppy Linux ...

  3. 「每日一题」有人上次在dy面试,面试官问我:vue数据绑定的实现原理。你说我该如何回答?

    关注「松宝写代码」,精选好文,每日一题 ​时间永远是自己的 每分每秒也都是为自己的将来铺垫和增值 作者:saucxs | songEagle 来源:原创 一.前言 文章首发在「松宝写代码」 2020. ...

  4. Python里的单下划线,双下划线,以及前后都带下划线的意义

    Python里的单下划线,双下划线,以及前后都带下划线的意义: 单下划线如:_name 意思是:不能通过from modules import * 导入,如需导入需要:from modules imp ...

  5. Python(三)基础篇之「模块&面向对象编程」

    [笔记]Python(三)基础篇之「模块&面向对象编程」 2016-12-07 ZOE    编程之魅  Python Notes: ★ 如果你是第一次阅读,推荐先浏览:[重要公告]文章更新. ...

  6. 「查缺补漏」巩固你的Redis知识体系

    Windows Redis 安装 链接: https://pan.baidu.com/s/1MJnzX_qRuNXJI09euzkPGA 提取码: 2c6w 复制这段内容后打开百度网盘手机App,操作 ...

  7. 「洛谷 P1801」黑匣子

    好像很久没有更过博客了,因为博主这几周很忙.其实是在搞颓. 题意很难懂,所以就不重复了.其实是懒. 一眼看上去这是个 \(Splay\) 裸题,直接插入一个数,查询区间第 \(K\) 大,但是这样太不 ...

  8. [转帖]「知乎知识库」— 5G

    「知乎知识库」— 5G 甜草莓 https://zhuanlan.zhihu.com/p/55998832 ​ 通信 话题的优秀回答者 已关注 881 人赞同了该文章 谢 知识库 邀请~本文章是几个答 ...

  9. 从0开始学习 GitHub 系列之「03.Git 速成」

    前面的 GitHub 系列文章介绍过,GitHub 是基于 Git 的,所以也就意味着 Git 是基础,如果你不会 Git ,那么接下来你完全继续不下去,所以今天的教程就来说说 Git ,当然关于 G ...

随机推荐

  1. KVM虚拟化环境准备

    1. 概述2. 环境准备2.1 硬件环境2.2 软件环境2.2.1 YUM安装软件包2.2.2 环境检查2.2.3 启动libvirtd服务2.3 网络环境2.3.1 复制网卡配置文件2.3.2 修改 ...

  2. 利用PowerUpSQL攻击SQL Server实例

    这篇博客简述如何快速识别被第三方应用使用的SQL Server实例,该第三方软件用PowerUpSQL配置默认用户/密码配置.虽然我曾经多次提到过这一话题,但是我认为值得为这一主题写一篇简短的博客,帮 ...

  3. Django文件上传(经典上传方式)

    经典文件上传方式 创建URL from django.contrib import admin from django.urls import path from django.conf.urls i ...

  4. js实现 页面加载 完成 后顺序 执行

    function addLoadEvent(func){ var oldonLoad = window.onload; if(typeof window.onload != 'function'){ ...

  5. Java 12 正式发布,8大新特性

    自 2 月 7 日开始,Java/JDK 12 就进入了 RC 阶段.按照发布周期,美国当地时间 3 月 19 日,也就是北京时间 20 号 Java 12 正式发布了! 1.Shenandoah:低 ...

  6. 基于udp的套接字编程

    一,简单明了了解udp套接字编程 客户端: #Author : Kelvin #Date : 2019/1/30 11:07 from socket import * ip_conf=("1 ...

  7. netty 之 telnet HelloWorld 详解

    前言 Netty是 一个异步事件驱动的网络应用程序框架, 用于快速开发可维护的高性能协议服务器和客户端. etty是一个NIO客户端服务器框架,可以快速轻松地开发协议服务器和客户端等网络应用程序.它极 ...

  8. 【效率神奇】Github丧心病狂的9个狠招

    Github,一个被业内朋友成为「全球最大的同性交友社区」的平台. 小时候遇到不会的字可以查新华字典.后来写作文我们可以通过作文书.或者文摘去找合适的素材.同样,写代码可以去Github上找适合自己的 ...

  9. 《k8s-1.13版本源码分析》-调度预选

    本文大纲 预选流程 predicate的并发 一个node的predicate predicates的顺序 单个predicate执行过程 具体的predicate函数 本系列文章已经开源到githu ...

  10. Dynamics CRM中跨域调用Web API 2

    关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复224或者20160611可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...