python functools.reduce_Python-functools模块(reduce、partial、lru_cache)
functools模块
reduce
functools.reduce(function, sequence[, initial]) -> value
就是减少的意思
初始值没提供就在可迭代对象中取一个
from functools importreduceprint(sum(range(10),100))print(reduce(lambda x,y:x+y,range(10),100))#输出都是 145
from functools importreduce
reduce(lambda x,y:x*y,range(1,5)) #求阶乘
上一次lambda函数的返回值会成为下一次的x
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=keywordsreturn newfunc
示例:
from functools importpartialimportinspectdefadd(x,y):return x +y
newadd= partial(add,y=10) #相当于固定了y这个参数,y必须通过keyword关键字传参
newadd(4),newadd(x=4),newadd(y=10,x=10),newadd(x=10,y=11),newadd(4,y=5) #y
#输出 (14, 14, 20, 21, 9)
inspect.signature(newadd)#
newadd(4,5) 错误的本质在于,它等价于 newadd(4,5,y=10) y值拿到了两个值,此处y则不能通过位置传参
def add(x,y,*args):return x + y +sum(args)
newadd= partial(add,1,2,3,4,5)
inspect.signature(newadd)# #签名是可变位置参数,则说明不能使用keyword传参
newadd(),newadd(10),newadd(3,4),newadd(3,4,5)#(15, 25, 22, 27)
#newadd(x=1,y=1) 错误写法,不能使用keyword传参
defadd(x,y):return x +y
newadd= partial(add,x=10,y=20)
newadd(),newadd(x=20,y=10)#(30, 30)
lru_cache
@functools.lru_cache(maxsize=128,typed=False)
lru表示最近最少使用,cache缓存
如果maxsize设置为None,则禁用LRU功能,并且缓存可以无限制的增长,maxsize是2的幂,LRU功能执行的最好
如果typed设置为True,则不同类型的函数参数将单独的缓存,例如,f(3),f(3.0)将被视为具有不同结果的不同调用
Python3.8简化了函数调用
importfunctools
@functools.lru_cachedefadd(x,y):pass
#等价于
@functools.lru_cache(maxsize=128)defadd(x,y):pass
importtimeimportfunctools
@functools.lru_cache()defadd(x,y):
time.sleep(3)print('-' * 20)return x +yprint(add(4,5))print(add(4,5))print(add(4.0,5))print(add(4,y=5))print(add(x=4,y=5))print(add(y=5,x=4))#前三种都视为同一种,会被缓存命中,后三种则不能被命中#输出
--------------------
9
应用
lru_cache装饰器的应用,求斐波那契数列的值
@functools.lru_cache()def fib(n,a=0,b=1):return 1 if n < 3 else fib(n-1) + fib(n-2)
fib(101)573147844013817084101
###############################
from functools importlru_cache
@lru_cache()def fib(n,a=0,b=1):return 1 if n < 3 else fib(n-1) + fib(n-2)
总结
lru_cache装饰器应用
使用前提:
同样的函数参数一定得得到同样的结果,至少是一段时间内,同样的输入得到同样的结果
计算代价高,函数执行时间过长
需要多次执行,每次计算的结果一样
缺点:
不支持过期缓存清理,key无法过期,失效
不支持清理
不支持分布式,是一个单机的缓存
适用场景:单机上需要空间换时间的地方,可以用缓存来将计算编程快速查询