假如一个函数定义了多个位置参数,那你每次调用时,都需要把这些个参数一个一个地传递进去。
比如下面这个函数,是用来计算 x的n次方
的。
def power(x, n):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
那我每次计算 x 的 n 次方,都要传递两个参数
>>> power(2, 2)
4
>>> power(3, 2)
9
后来我发现,我很多时候都是计算平方值,很多会去计算三次方,四次方。
那有什么办法可以偷个懒吗?
答案是,有。可以使用 偏函数
。
偏函数(Partial Function),可以将某个函数的常用参数进行固定,避免每次调用时都要指定。
使用偏函数,需要导入 functools.partial
,然后利用它创建一个新函数,新函数的 n 固定等2。
具体使用请看下面的示例
>>> from functools import partial
>>> power_2=partial(power, n=2)
>>> power_2(2)
4
>>> power_2(3)
9
根据传入参数类型的不同而调用不同的函数逻辑体,这种实现我们称之为泛型。在 Python 中叫做 singledispatch
。
它使用方法极其简单,只要被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')
【错误】:参数类型不同,无法拼接!!
审核编辑:符乾江
全部0条评论
快来发表一下你的评论吧 !