partial方法
- 偏函数, 把函数部分的参数固定下来, 相当于为部分的参数添加了一个固定的默认值, 形成一个新的函数并返回
- 从partial生成的新函数, 是对原函数的封装
partial函数本质:
def partial(func, *args, **keywords):
def newfunc(*fargs, **fkeywords): # 包装函数
newkeywords = keywords.copy()
newkeywords.update(fkeywords)
return func(*args, *fargs, **newkeywords)
newfunc.func = func # 保留原函数
newfunc.args = args # 保留原函数的位置参数
newfunc.keywords = keywords # 保留原函数的关键字参数
return newfunc
举例:
偏函数固定原函数一个参数的值, 相当于默认值
看返回函数的签名, y参数变成了带缺省值的Keyword-Only
返回的新函数可以接收的参数:
- 单参传参(视为x的位置传参, y用默认值)
- 接收x的位置参数, y用关键字传参
- 接收两个关键字传参
偏函数的应用:
def update_wrapper(wrapper,
wrapped,
assigned = WRAPPER_ASSIGNMENTS,
updated = WRAPPER_UPDATES):
for attr in assigned:
try:
value = getattr(wrapped, attr)
except AttributeError:
pass
else:
setattr(wrapper, attr, value)
for attr in updated:
getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
return wrapper
def wraps(wrapped,
assigned = WRAPPER_ASSIGNMENTS,
updated = WRAPPER_UPDATES):
return partial(update_wrapper, wrapped=wrapped,
assigned=assigned, updated=updated)
这段是function模块下的update-wrapper函数的源码
作用:不改变使用装饰器原有函数的结构(如__name__, __ doc__)
update-wrapper函数需要接收两个参数, 在wraps函数中用偏函数把wrapped参数固定下来, 就可以用wraps函数用单参传参了
举例:
这是一个计算运行时间的装饰器:
- wraps函数写在定义wrapper函数前面, 不改变add函数原有的"__ name __ , __ doc__"
- wraps接收一个参数即可
- wraps函数在装饰器里为了不改变函数原有的性质是很常用的
cache缓存
@functools.lru_cache(maxsize=128, typed=False)
- Least-recently-used装饰器。lru,最近最少使用。cache缓存
- 如果maxsize设置为None,则禁用LRU功能,并且缓存可以无限制增长。当maxsize是二的幂时,LRU功能执行得最好
- 如果typed设置为True,则不同类型的函数参数将单独缓存。例如,f(3)和f(3.0)将被视为具有不同结果的不同调用
举例:
在add函数前面用cache装饰器, 用logger装饰器查看运行时间
对add函数用同样的参数连续调用三次, 可以看到第二次第三次直接出现结果, 运行时间0秒, 也就是第二次第三次调用用缓存直接出结果的
lru_cache装饰器应用:
本质是函数调用的参数=>返回值
使用前提:
- 同样的函数参数一定得到同样的结果
- 函数执行时间很长,且要多次执行
缺点:
- 不支持缓存过期,key无法过期、失效
- 不支持清除操作
- 不支持分布式,是一个单机的缓存
适用场景,单机上需要空间换时间的地方,可以用缓存来将计算变成快速的查询