多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
# 5.7 【进阶】泛型函数的使用 根据传入参数类型的不同而调用不同的函数逻辑体,这种实现我们称之为泛型。在 Python 中叫做 `singledispatch`。 `singledispatch` 是 PEP443 中引入的,如果你对此有兴趣,PEP443 应该是最好的学习文档:https://www.python.org/dev/peps/pep-0443/ 它使用方法极其简单,只要被`singledispatch` 装饰的函数,就是一个`single-dispatch` 的泛函数(`generic functions`)。 - **单分派**:根据一个参数的类型,以不同方式执行相同的操作的行为。 - **多分派**:可根据多个参数的类型选择专门的函数的行为。 - **泛函数**:多个函数绑在一起组合成一个泛函数。 这边举个简单的例子。 ```python 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 等,不同数据类型的拼接方式各不相同,所以我这里我写了一个通用的函数,可以根据对应的数据类型对选择对应的拼接方式拼接,而且不同数据类型我还应该提示无法拼接。以下是简单的实现。 ```python 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 的话,你可能会写出这样的代码。 ```python 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') 【错误】:参数类型不同,无法拼接!! ```