在推导Fib数列过程中利用Python装饰器的实现缓存,解决利用递归实现Fib数列的过程中,出现的大量重复计算,进而影响性能的问题
ps:不借助Python中自带的解决缓存问题的解释器
from functools import lru_cache
from functools import wraps
import time
# 官方自带的缓存装饰器,可结合场景使用
# from functools import lru_cache
def timeit(func):
"""打印被装饰函数运行总时间的装饰器"""
# @wraps保留被装饰函数的函数名和帮助文档, 否则是wrapper的信息.
@wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print("%s函数运行总时间为%fs" % (func.__name__, end_time - start_time))
return result
return wrapper
def fib_cache(func):
"""对被装饰函数(fib数列生成器)的推导结果进行缓存的装饰器"""
caches = {1: 1, 2: 1, 3: 2, 4: 3, 5: 5}
# @wraps保留被装饰函数的函数名和帮助文档, 否则会是wrapper的信息.
@wraps(func)
def wrapper(num):
# 如果缓存中能找到第num个Fib数列的值, 直接返回。
if num in caches:
return caches.get(num)
# 如果缓存中不能找到第num个Fib数列的值,
# 1). 先执行函数func(num)计算结果。
# 2). 然后将将计算的结果存储在缓存中。并返回计算结果
else:
result = func(num)
caches[num] = result
return result
return wrapper
@fib_cache # fib1 = fib_cache(fib1)
def fib1(num):
"""计算Fib数列的第num 个值"""
if num in (1, 2):
return 1
else:
return fib1(num - 1) + fib1(num - 2)
def fib2(num):
"""计算Fib数列的第num 个值"""
if num in (1, 2):
return 1
else:
return fib2(num - 1) + fib2(num - 2)
# 利用定义的性能装饰器对使用缓存的fib生成器的运行时间进行检测
@timeit # use_cache = timeit(use_cache)
def use_cache():
result = fib1(20)
print(result)
# 利用定义的性能装饰器对未使用缓存的fib生成器的运行时间进行检测
@timeit
def no_cache():
result = fib2(20)
print(result)
if __name__ == '__main__':
use_cache()
no_cache()
执行结果: