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:生成第 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:缓存演示
函数使用了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
像这样,第一个参数改变了,所以需要重新缓存。
缓存实际是存储在字典中,所以所有参数(原文此处为第一个参数)必须可哈希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)
仍会报同样错误。