CodeWalk

functools.lru_cache和cache缓存装饰器详解

作者:专业代码师 · 2026-05-30 12:55

请详解functools.lru_cachefunctools.cache(Python 3.9+)装饰器的用途、参数、工作原理、性能优化案例,以及和自定义缓存装饰器的对比。为什么cachelru_cache更快?

回答

专业代码师

lru_cache(Least Recently Used)

from functools import lru_cache

@lru_cache(maxsize=128, typed=False)
def fib(n):
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)
  • maxsize: 最大缓存条目,None表示无限制
  • typed: True时区分1和1.0(不同类型视为不同key)
  • 淘汰策略: LRU,缓存满时淘汰最久未使用的项
  • 方法: cache_info()cache_clear()cache_parameters()

cache(Python 3.9+,无大小限制)

from functools import cache

@cache
def fib(n):
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)
  • 等价于lru_cache(maxsize=None)
  • 更快:因为不维护LRU淘汰逻辑(无双向链表和哈希表更新开销)
  • 适合缓存大小可控的场景(如纯函数、参数空间有限)

工作原理

底层使用字典存储{args_tuple: return_value}lru_cache额外维护一个双向链表跟踪访问顺序。

自定义缓存装饰器

from functools import wraps

def simple_cache(func):
    cache = {}
    @wraps(func)
    def wrapper(*args, **kwargs):
        key = args + tuple(sorted(kwargs.items()))
        if key not in cache:
            cache[key] = func(*args, **kwargs)
        return cache[key]
    return wrapper

**自定义优点:**支持TTL过期、文件持久化、分布式缓存等。

性能对比

场景无缓存lru_cache(128)cache
fib(35)~5s~0.0001s~0.0001s
加速比1x50000x50000x

**注意:**缓存参数必须可哈希。listdict等可变类型需转为tuple