functools.lru

xiaoxiao2021-02-28  24

在functools这个模块中,有lru_cache这个一个神奇的装饰器存在。functools.lru_cache的作用主要是用来做缓存,他能把相对耗时的函数结果进行保存,避免传入相同的参数重复计算。同时,缓存并不会无限增长,不用的缓存会被释放。

举fluent python中的例子来说: 首先实现一个计算运行时间的装饰器

import time import functools def clock(func): # functools.wraps(func)装饰器的作用是将func函数的相关属性复制到clock中 # 比如说__name__, __doc__等等 @functools.wraps(func) def clocked(*args, **kwargs): t0 = time.time() result = func(*args, **kwargs) elapsed = time.time() - t0 name = func.__name__ arg_lst = [] if args: arg_lst.append(', '.join(repr(arg) for arg in args)) if kwargs: pairs = ['%s=%r' % (k, w) for k, w in sorted(kwargs.items())] arg_lst.append(', '.join(pairs)) arg_str = ', '.join(arg_lst) print('[%0.8fs] %s(%s) -> %r ' % (elapsed, name, arg_str, result)) return result

接下来写一个生成第n个斐波纳契数的函数

from clockdeco import clock @clock def fibonacci(n): if n < 2: return n return fibonacci(n-2) + fibonacci(n-1) if __name__=='__main__': print(fibonacci(6))

运行结果:

[0.00000041s] fibonacci(0) -> 0 [0.00000051s] fibonacci(1) -> 1 [0.00003454s] fibonacci(2) -> 1 [0.00000025s] fibonacci(1) -> 1 [0.00000026s] fibonacci(0) -> 0 [0.00000024s] fibonacci(1) -> 1 [0.00000743s] fibonacci(2) -> 1 [0.00001429s] fibonacci(3) -> 2 [0.00005602s] fibonacci(4) -> 3 [0.00000022s] fibonacci(1) -> 1 [0.00000023s] fibonacci(0) -> 0 [0.00000021s] fibonacci(1) -> 1 [0.00000672s] fibonacci(2) -> 1 [0.00001346s] fibonacci(3) -> 2 [0.00000021s] fibonacci(0) -> 0 [0.00000022s] fibonacci(1) -> 1 [0.00000691s] fibonacci(2) -> 1 [0.00000022s] fibonacci(1) -> 1 [0.00000027s] fibonacci(0) -> 0 [0.00000022s] fibonacci(1) -> 1 [0.00000708s] fibonacci(2) -> 1 [0.00001363s] fibonacci(3) -> 2 [0.00002687s] fibonacci(4) -> 3 [0.00004682s] fibonacci(5) -> 5 [0.00011096s] fibonacci(6) -> 8 8

有大量的重复函数计算在整个运行过程中,比如fibonacci(1),fibonacci(2)就分别运行了多次。 现在给fibonacci()函数加上@functools.lru_cache()装饰器进行缓存实现

from clockdeco import clock @functools.lru_cache() @clock def fibonacci(n): if n < 2: return n return fibonacci(n-2) + fibonacci(n-1) if __name__=='__main__': print(fibonacci(6))

一共就多了一行代码,那看看运行结果如何。

[0.00000041s] fibonacci(0) -> 0 [0.00000054s] fibonacci(1) -> 1 [0.00004040s] fibonacci(2) -> 1 [0.00000104s] fibonacci(3) -> 2 [0.00005465s] fibonacci(4) -> 3 [0.00000072s] fibonacci(5) -> 5 [0.00006876s] fibonacci(6) -> 8 8

不使用lru_cache装饰器时的运行时间是0.00011096s,加上以后变成了0.00006876s。这个效率增加的杠杆的,尤其在充斥这大量重复计算时,它更能够为程序的运行节省大量的时间。

另外:functools.lru_cache(maxsize=128, typed=False)有两个可选参数,我们来看看他们分别代表的意义。

* maxsize代表缓存的内存占用值,超过这个值之后,就的结果就会被释放,然后将新的计算结果进行缓存,其值应当设为2的幂 *

* typed若为True,则会把不同的参数类型得到的结果分开保存 *

ps:

@functools.lru_cache() @clock def fibonacci(n): if n < 2: return n return fibonacci(n-2) + fibonacci(n-1)

这段代码中叠加使用了两个装饰器,那具体这两个装饰器的先后顺序是怎么样的。 举个例子:

@d1 @d2 def f(): print('f')

等于

def f(): print('f') f = d1(d2(f))

也就是说从下往上依次执行

转载请注明原文地址: https://www.6miu.com/read-1400120.html

最新回复(0)