python functools.lru_cache()装饰器

detectron2中logger模块中引用functools.lru_cache()装饰器,代码如下:

@functools.lru_cache()  # so that calling setup_logger multiple times won't add many handlers
def setup_logger(
        output=None, distributed_rank=0, *, color=True, name="detectron2", abbrev_name=None
):

该函数是一个装饰器,为函数提供缓存功能。在下次以相同参数调用时直接返回上一次的结果。

1、lru_cache装饰器使用

例1:生成第 n 个斐波纳契数,这种慢速递归函数适合使用 lru_cache

import time

def fibonacci(n):
    """斐波那契函数"""
    if n < 2:
        return n
    return fibonacci(n - 2) + fibonacci(n - 1)


if __name__ == '__main__':
    stime = time.time()
    print(fibonacci(34))  # 没有使用缓存,则需要几秒钟的时间
    print("total time is %.3fs" % (time.time() - stime))
=>
    5702887
    total time is 1.335s

如果没有使用缓存,则需要几秒钟的时间,像下面这样使用缓存后,瞬间就可以计算出结果。

import datetime
import functools

@functools.lru_cache(maxsize=300)
def fibonacci(n):
    """斐波那契函数"""
    if n < 2:
        return n
    return fibonacci(n - 2) + fibonacci(n - 1)

如果使用了lru_cache,计算用时被大大减少,测试计算时间为0s。这是因为我们在使用fibonacci递归函数时,会重复计算值。使用了lru_cache后,所有的重复计算只会执行一次。

2、注意事项

2.1、缓存是按照参数作为键

缓存是按照参数作为键。(此处原作者写的是按照第一个参数作为键,实测按照所有参数作为键值)

例2:缓存演示

函数使用了lru_cache缓存,所以只打印一次执行计算。

import functools

@functools.lru_cache(maxsize=100)
def my_sum(a, b):
    print('执行计算')
    return a+b

if __name__ == '__main__':
    t1 = my_sum(1, 2)
    print(t1)
    t2 = my_sum(1, 2)
    print(t2)
=>
执行计算
3
3

例3:参数改变,重新缓存

if __name__ == '__main__':
    t1 = my_sum(1, 2)
    print(t1)
    t2 = my_sum(2, 1)
    print(t2)
=>
执行计算
3
执行计算
3    

像这样,第一个参数改变了,所以需要重新缓存。

2.2、所有参数必须可哈希hash

缓存实际是存储在字典中,所以所有参数(原文此处为第一个参数)必须可哈希hash.

from functools import lru_cache

@lru_cache(maxsize=100)
def list_sum(nums: list):
    return sum(nums)

上述函数无法使用缓存,会报错:TypeError: unhashable type: 'list'

from functools import lru_cache

@lru_cache(maxsize=100)
def list_sum(a=1, nums: list):
    return sum(nums)

仍会报同样错误。

 

你可能感兴趣的:(python,python,缓存,functools,lru_cache,pytorch)