Python-functools模块(reduce、partial、lru_cache)

functools模块

reduce

  functools.reduce(function, sequence[, initial]) -> value

  就是减少的意思

  初始值没提供就在可迭代对象中取一个

from functools import reduce 
print(sum(range(10),100))

print(reduce(lambda x,y:x+y,range(10),100))

#输出都是 145 
from functools import reduce

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 = keywords
    return newfunc

示例:

from functools import partial
import inspect
def add(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)
#<Signature (x, *, y=10)>


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)

#<Signature (*args)> #签名是可变位置参数,则说明不能使用keyword传参
newadd(),newadd(10),newadd(3,4),newadd(3,4,5)

#(15, 25, 22, 27)

#newadd(x=1,y=1) 错误写法,不能使用keyword传参
def add(x,y):
    return x + y
newadd = partial(add,x=10,y=20)
inspect.signature(newadd)
#<Signature (*, 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简化了函数调用

import functools 

@functools.lru_cache
def add(x,y):
    pass

#等价于
import functools 

@functools.lru_cache(maxsize=128def add(x,y):
    pass

 

示例:

import time 
import functools 

@functools.lru_cache()
def add(x,y):
    time.sleep(3)
    print('-' * 20)
    return x + y


print(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
9
9
--------------------
9
--------------------
9
--------------------
9

 

应用

lru_cache装饰器的应用,求斐波那契数列的值

import functools

@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 import lru_cache

@lru_cache()
def fib(n,a=0,b=1):
    return 1 if n < 3 else fib(n-1) + fib(n-2)
fib(101)

573147844013817084101

 

总结

lru_cache装饰器应用

使用前提:

  同样的函数参数一定得得到同样的结果,至少是一段时间内,同样的输入得到同样的结果

  计算代价高,函数执行时间过长

  需要多次执行,每次计算的结果一样

 

缺点:

  不支持过期缓存清理,key无法过期,失效

  不支持清理

  不支持分布式,是一个单机的缓存

 

  适用场景:单机上需要空间换时间的地方,可以用缓存来将计算编程快速查询

 

posted @ 2020-04-25 20:16  Alrenn  阅读(256)  评论(0)    收藏  举报