Python中使用缓存加速计算
已于 2025年01月21日 11:58 修改
访问次数:12
在 Python 中,缓存(Caching)是指将计算的结果保存在内存中,以避免重复的计算过程,从而提高程序的性能。Python 提供了一些现成的类和装饰器来实现缓存功能,最常见的是 functools.lru_cache 装饰器、cachetools 库以及自定义的缓存机制。
1. functools.lru_cache 装饰器
functools.lru_cache 是 Python 内建的一个装饰器,用于为函数添加缓存功能,减少重复计算。LRU(Least Recently Used)表示最少使用缓存策略,即当缓存空间满时,会删除最久未使用的缓存项。
使用示例:
from functools import lru_cache
@lru_cache(maxsize=None) # maxsize=None 表示无限缓存
def fibonacci(n):
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(10)) # 第一次计算时,会缓存结果
print(fibonacci(10)) # 第二次调用时,直接返回缓存结果
参数说明:
maxsize: 控制缓存的大小。默认情况下,maxsize=128。当缓存超过最大大小时,LRU 缓存会自动清理掉最久未使用的项。设置为None表示无限缓存。typed: 如果为True,则对于不同类型的参数会使用不同的缓存。例如,fibonacci(3)和fibonacci(3.0)会被视为不同的调用。
2. cachetools 库
cachetools 是一个第三方库,提供了更多灵活的缓存策略,支持多种缓存类型,比如 LRU、TTL(Time To Live)、LFU(Least Frequently Used)等。
安装:
pip install cachetools
使用示例:
import cachetools
# 使用 LRU Cache
cache = cachetools.LRUCache(maxsize=100)
# 放入缓存
cache['key'] = 'value'
# 获取缓存
print(cache['key']) # 输出 'value'
# 使用带 TTL 的缓存
cache = cachetools.TTLCache(maxsize=100, ttl=60) # 设置缓存的 TTL 为 60秒
cache['key'] = 'value'
缓存策略:
LRUCache: LRU 缓存,类似于functools.lru_cache,但功能更丰富。TTLCache: 支持设置缓存的生存时间(TTL),当超过指定时间后,缓存会被自动清除。LFUCache: 支持最不常用缓存策略,较少使用的项会被优先清除。
3. 自定义缓存机制
如果你有特殊需求,也可以通过自定义类来实现缓存机制。例如,可以实现一个简单的字典缓存,或者使用其他存储机制(如文件、数据库等)。
使用示例:
class SimpleCache:
def __init__(self, max_size=100):
self.cache = {}
self.max_size = max_size
def get(self, key):
return self.cache.get(key)
def set(self, key, value):
if len(self.cache) >= self.max_size:
self.cache.pop(next(iter(self.cache))) # 移除最老的元素
self.cache[key] = value
# 使用自定义缓存
cache = SimpleCache(max_size=2)
cache.set('a', 1)
cache.set('b', 2)
print(cache.get('a')) # 输出 1
cache.set('c', 3) # 超过最大缓存大小,移除 'a'
print(cache.get('a')) # 输出 None,因为 'a' 被移除
4. @cached_property 装饰器(functools)
@cached_property 是 functools 模块中的另一个装饰器,通常用于对象的属性缓存。当你首次访问某个属性时,会调用相应的函数并缓存结果。之后访问该属性时,会直接返回缓存的结果。
使用示例:
from functools import cached_property
class ExpensiveCalculation:
@cached_property
def result(self):
print("Performing expensive calculation...")
return 42
obj = ExpensiveCalculation()
print(obj.result) # 第一次调用会执行计算并缓存结果
print(obj.result) # 第二次调用时直接使用缓存的结果
特点:
- 适用于计算量较大的属性。
- 在第一次访问时计算,并缓存结果;之后直接使用缓存。
5. memoization(手动实现)
如果你希望对函数进行简单的记忆化缓存(只缓存函数的输入和输出),可以通过手动实现一个字典缓存:
使用示例:
def memoize(func):
cache = {}
def wrapper(*args):
if args in cache:
return cache[args]
result = func(*args)
cache[args] = result
return result
return wrapper
@memoize
def expensive_function(x, y):
print("Computing...")
return x + y
print(expensive_function(1, 2)) # 计算并缓存结果
print(expensive_function(1, 2)) # 使用缓存结果,不再计算
总结
functools.lru_cache: 内建装饰器,支持 LRU 缓存,适用于函数结果的缓存。cachetools: 第三方库,支持多种缓存策略(如 LRU、TTL、LFU 等)。@cached_property: 用于缓存对象属性的计算结果。- 自定义缓存:可以根据需求手动实现缓存机制,灵活性高。
这些缓存工具可以帮助你优化性能,避免重复计算,尤其是在涉及到复杂或耗时计算的场景中。
评论(0)