# lru_cache 即 least recent used cache # 它实现的功能是存储函数的结果,避免传入相同参数时函数的重复计算。 # 用在递归算法中可以很大程度上缩短递归次数,和我们自己写一个容器 # 做备忘录的功能是一样的,不过lru_cache是使用字典来记录函数结果,这 # 个备忘字典一样是以函数参数作为键,函数结果作为值。所以被它修饰的 # 函数的参数必须都是可散列的:如 int tuple str frozenset
用它可以很方便的优化递归算法
Question:
# 最少找零问题
"""
题:设货币面值(1,5,10,25),输入找零数值后返回最少找零数目?
思路:
1.找零数值在货币面值中就只有找零一次
2.找零数值不在货币面值中时:取(1)(2)(3)(4)中的最小值
(1)找一张1元 + 找 change-1元的最少找零数
(2)找一张5元+找change-5 元的最少找零数
(3)找一张10元+找change-10 元的最少找零数
(4)找一张25元+找change-25 元的最少找零数
"""
# 代码实现
import functools
@functools.lru_cache(maxsize=128)
def least_change_num(change, currency):
if change in currency:
return 1
else:
return 1 + min(
least_change_num(change - substraction, currency) for substraction in currency if change > substraction)
print(least_change_num(163, (1, 5, 10, 25)))
为了进一步展现这个修饰器的强大与便捷,下面我自己来实现下备忘功能
代码量大得多,也没有直接使用lru_cache装饰器直观。
def func():
known = {}
# 对于least_change_num2来说,known是它的自由变量
def least_change_num2(change, currency):
# 使用自由变量前先做一个非本地变量申明,让解释器不要因为我们在内层函数修改自由变量是误认为自由变量是局部变量
nonlocal known
if change in currency:
known[change] = 1
return 1
else:
for new_change in [change - minus for minus in currency if minus < change]:
if new_change not in known.keys():
if change not in known.keys():
known[change] = least_change_num2(new_change, currency) + 1
elif least_change_num2(new_change, currency) + 1 < known[change]:
known[change] = least_change_num2(new_change, currency) + 1
else:
if change not in known.keys():
known[change] = known[new_change] + 1
elif known[new_change] + 1 < known[change]:
known[change] = known[new_change] + 1
return known[change]
return least_change_num2
print(func()(163, (1, 5, 10, 25)))
运行结果: