第三章:算法-functools:管理函数的工具-缓存

3.1.3 缓存
lru_cache()修饰符将一个函数包装在一个“最近最少使用的”缓存中。函数的参数用来建立一个散列键,然后映射到结果。后续的调用如果有相同的参数,就会从这个缓存获取值而不会再次调用函数。这个修饰符还会为函数增加方法来检查缓存的状态(cache_info())和清空缓存(cache_clear())。

import functools

@functools.lru_cache()
def expensive(a,b):
    print('expensive({},{})'.format(a,b))
    return a * b

MAX = 2

print('First set of calls:')
for i in range(MAX):
    for j in range(MAX):
        expensive(i,j)
print(expensive.cache_info())

print('\nSecond set of calls:')
for i in range(MAX + 1):
    for j in range(MAX + 1):
        expensive(i,j)
print(expensive.cache_info())

print('\nClearing cache:')
expensive.cache_clear()
print(expensive.cache_info())

print('\nThird set of calls:')
for i in range(MAX):
    for j in range(MAX):
        expensive(i,j)
print(expensive.cache_info())

这个例子在一组嵌套循环中执行了多个expensive()调用。第二次调用时有相同的参数值,结果在缓存中。清空缓存并再次运行循环时,这些值必须重新计算。
运行结果:
在这里插入图片描述
为了避免一个长时间运行的紧凑导致缓存无限制地扩张,要指定一个最大大小。默认为128个元素,不过对于每个缓存可以用maxsize参数改变这个大小。

import functools

@functools.lru_cache(maxsize=2)
def expensive(a,b):
    print('called expensive({},{})'.format(a,b))
    return a * b

def make_call(a,b):
    print('({},{})'.format(a,b),end=' ')
    pre_hits = expensive.cache_info().hits
    expensive(a,b)
    post_hits = expensive.cache_info().hits
    if post_hits > pre_hits:
        print('cache hit')

print('Establish the cache')
make_call(1,2)
make_call(2,3)

print('\nUse cached items')
make_call(1,2)
make_call(2,3)

print('\nCompute a new value,triggering cache expiration')
make_call(3,4)

print('\nCache still contains one old item')
make_call(2,3)

print('\nOldest item needs to be recomputed')
make_call(1,2)

在这个例子中,缓存大小设置为2个元素。使用第三组不同的参数(3,4)时,缓存中最老的元素会被清除,代之以这个新结果。
运行结果:
在这里插入图片描述
lru_cache()管理的缓存中键必须是可散列的,所以对于用缓存查找包装的函数,它的所有参数都必须是可散列的。

import functools

@functools.lru_cache(maxsize=2)

def expensive(a,b):
    print('called expensive({},{})'.format(a,b))
    return a * b

def make_call(a,b):
    print('({},{})'.format(a,b),end=' ')
    pre_hits = expensive.cache_info().hits
    expensive(a,b)
    post_hits = expensive.cache_info().hits
    if post_hits > pre_hits:
        print('cache hit')

make_call(1,2)

try:
    make_call([1],2)
except TypeError as err:
    print('ERROR:{}'.format(err))

try:
    make_call(1,{'2':'two'})
except TypeError as err:
    print('ERROR:{}'.format(err))

如果将一个不能散列的对象传入这个函数,则会产生一个TypeError。
运行结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值