导读:本期聚焦于小伙伴创作的《Python如何实现高效的缓存机制?functools.lru_cache扩展方法有哪些》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Python如何实现高效的缓存机制?functools.lru_cache扩展方法有哪些》有用,将其分享出去将是对创作者最好的鼓励。

Python的functools.lru_cache是内置的LRU(最近最少使用)缓存装饰器,能够自动缓存函数的返回值,当相同参数再次调用函数时直接返回缓存结果,避免重复计算。但在实际开发中,我们常常需要更灵活的缓存能力,比如缓存过期、自定义淘汰规则、支持异步函数等,这就需要对lru_cache进行扩展。

Python如何实现高效的缓存机制?functools.lru_cache扩展方法有哪些

functools.lru_cache基础用法

原生lru_cache的使用非常简单,只需要装饰目标函数即可,它支持设置maxsize参数指定最大缓存数量,设置为None时表示缓存无上限。

import functools
import time

# 使用lru_cache装饰函数,最大缓存128个结果
@functools.lru_cache(maxsize=128)
def compute_square(n):
    time.sleep(1)  # 模拟耗时计算
    return n * n

# 第一次调用,会执行计算
print(compute_square(5))  # 等待1秒后输出25
# 第二次调用相同参数,直接返回缓存结果
print(compute_square(5))  # 立即输出25

扩展场景一:添加缓存过期功能

原生lru_cache没有缓存过期机制,缓存结果会一直存在直到被淘汰。我们可以通过包装lru_cache,给每个缓存结果添加时间戳,在获取缓存时判断是否过期。

import functools
import time

def lru_cache_with_ttl(ttl=60, maxsize=128):
    """带过期时间的lru_cache扩展装饰器,ttl单位为秒"""
    def decorator(func):
        # 创建原生lru_cache装饰器
        cached_func = functools.lru_cache(maxsize=maxsize)(func)
        # 存储缓存的时间戳,key和cached_func的缓存key对应
        cache_time = {}

        def wrapper(*args, **kwargs):
            # 生成缓存key,lru_cache的key是args和frozenset(kwargs.items())
            key = args
            if kwargs:
                key += tuple(sorted(kwargs.items()))
            current_time = time.time()
            # 检查缓存是否存在且未过期
            if key in cache_time and current_time - cache_time[key] < ttl:
                return cached_func(*args, **kwargs)
            # 缓存不存在或已过期,重新计算
            result = func(*args, **kwargs)
            cached_func.cache_clear()  # 清除旧缓存,重新缓存
            cached_func(*args, **kwargs)  # 存入新结果
            cache_time[key] = current_time
            return result
        return wrapper
    return decorator

# 使用示例,缓存有效期10秒
@lru_cache_with_ttl(ttl=10)
def get_data(param):
    return f"data_{param}_{time.time()}"

print(get_data("test"))  # 第一次调用,生成新数据
time.sleep(5)
print(get_data("test"))  # 5秒后调用,缓存未过期,返回相同结果
time.sleep(6)
print(get_data("test"))  # 总共11秒后调用,缓存过期,生成新数据

扩展场景二:支持异步函数缓存

原生lru_cache不支持异步函数,直接装饰async函数会返回协程对象而不是缓存结果,需要针对异步函数做适配。

import functools
import asyncio

def async_lru_cache(maxsize=128):
    """支持异步函数的lru_cache扩展装饰器"""
    def decorator(func):
        # 用原生lru_cache缓存协程的结果,注意这里缓存的是已经执行完成的返回值
        cache = functools.lru_cache(maxsize=maxsize)

        @functools.wraps(func)
        async def wrapper(*args, **kwargs):
            key = args
            if kwargs:
                key += tuple(sorted(kwargs.items()))
            # 检查缓存是否存在
            if key in cache._cache:  # 访问内部缓存字典,注意不同Python版本可能有差异
                return cache(key)
            # 执行异步函数获取结果
            result = await func(*args, **kwargs)
            # 存入缓存
            cache(key, result)
            return result
        return wrapper
    return decorator

# 使用示例
@async_lru_cache(maxsize=64)
async def async_fetch_data(url):
    await asyncio.sleep(1)  # 模拟异步请求
    return f"content_of_{url}"

async def main():
    print(await async_fetch_data("https://ipipp.com/test"))  # 等待1秒输出
    print(await async_fetch_data("https://ipipp.com/test"))  # 立即输出缓存结果

asyncio.run(main())

扩展场景三:自定义淘汰策略

原生lru_cache采用最近最少使用策略淘汰缓存,如果我们需要实现FIFO(先进先出)等其他淘汰策略,可以基于lru_cache的缓存管理接口进行扩展。

import functools
from collections import OrderedDict

def fifo_cache(maxsize=128):
    """FIFO淘汰策略的缓存装饰器"""
    def decorator(func):
        cache = OrderedDict()

        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            key = args
            if kwargs:
                key += tuple(sorted(kwargs.items()))
            # 命中缓存直接返回
            if key in cache:
                return cache[key]
            # 未命中,执行函数
            result = func(*args, **kwargs)
            # 缓存达到上限,删除最早加入的缓存
            if len(cache) >= maxsize:
                cache.popitem(last=False)
            cache[key] = result
            return result
        return wrapper
    return decorator

# 使用示例
@fifo_cache(maxsize=3)
def add(a, b):
    return a + b

print(add(1, 2))  # 缓存{ (1,2):3 }
print(add(2, 3))  # 缓存{ (1,2):3, (2,3):5 }
print(add(3, 4))  # 缓存{ (1,2):3, (2,3):5, (3,4):7 }
print(add(4, 5))  # 缓存满,删除(1,2),缓存{ (2,3):5, (3,4):7, (4,5):9 }

扩展注意事项

在对functools.lru_cache进行扩展时,需要注意以下几点:

  • 被缓存的函数参数必须是可哈希的,否则无法作为缓存的key,这也是原生lru_cache的要求
  • 扩展缓存过期功能时,尽量避免频繁调用cache_clear()方法,否则会清空所有缓存,影响性能
  • 异步缓存扩展中,访问lru_cache的内部缓存属性时,需要注意不同Python版本的兼容性差异
  • 自定义淘汰策略时,如果需要保留lru_cache的统计功能,可以手动维护cache_info相关的属性

通过上述扩展方式,我们可以让functools.lru_cache适配更多业务场景,在提升程序性能的同时满足个性化的缓存需求。

Pythonfunctools_lru_cache缓存机制缓存扩展修改时间:2026-07-16 07:51:36

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。