Python之@cache装饰器的使用及说明

Written by

in

文章目录
  • @cache 是 Python 3.9 引入的新功能,来源于标准库 functools 模块。它的作用是 对函数结果进行缓存(记忆化 memoization),从而避免重复计算,提高程序性能。 它的定义方式非常简单: from functools import cache @cache def some_function(…): … 当你用 @cache 修饰一个函数时,Python 会将该函数的输入参数与计算结果自动保存到一个缓存(字典)中。当后续调用该函数且参数完全相同时,不会再次执行函数体的计算逻辑,而是直接返回之前缓存的结果。
  • @cache 装饰器内部其实是基于 functools.lru_cache 实现的,它等价于: from functools import lru_cache cache = lru_cache(maxsize=None) 也就是说: 无限大小缓存:maxsize=None 表示缓存结果没有数量限制,会根据需要一直增长(直到你的内存允许)。 键值匹配:缓存根据参数 值 判断是否命中(必须是可哈希类型,如数字、字符串、元组等)。 返回缓存结果:命中缓存时,直接返回结果而不执行函数计算。
  • 1. 基本示例:递归斐波那契数列 from functools import cache @cache def fib(n): print(f”计算 fib({n})”) if n < 2: return n return fib(n – 1) + fib(n – 2) print(fib(10)) # 第一次需要计算 print(fib(10)) # 第二次直接命中缓存,不会重新计算 运行效果: 第一次调用会完整计算 fib(10),输出多行 "计算 fib(n)" 的提示信息。 第二次调用相同参数,直接返回缓存值,不输出任何计算日志。 2. 模拟耗时计算 import time from functools import cache @cache def slow_function(x): print(f”开始计算 {x}…”) time.sleep(2) # 模拟耗时 return x * x # 首次调用耗时 print(slow_function(5)) # 第二次调用相同参数时几乎立即返回 print(slow_function(5)) 在实际场景中,如果一个函数计算代价高(如数据库查询、大文件解析、复杂计算等),使用 @cache 能显著减少重复工作。
  • 适用场景 适合纯函数(函数结果只依赖输入参数,且不会产生副作用)。 不适合需要每次实时更新的函数(例如获取当前时间、外部数据接口)。 参数限制 参数必须可哈希(hashable),如整数、字符串、元组等。 如果传入不可哈希类型(如列表、字典),会报错 TypeError: unhashable type。 内存占用 @cache 默认缓存无限大小,可能造成内存占用增加;如果希望限制缓存大小,应使用 lru_cache(maxsize=…) 来控制。 缓存失效 @cache 没有内置超时或自动失效机制,缓存会一直保留直到程序结束或手动清除: your_function.cache_clear()
  • 特性 @cache @lru_cache 缓存大小限制 无限 (maxsize=None) 可自定义 maxsize 缓存策略 简单字典保存 LRU(Least Recently Used)淘汰 用途 适合始终命中缓存且参数种类有限 适合缓存有限结果并自动淘汰旧数据
  • @cache 能让函数的重复调用变得快速,尤其适合计算昂贵且参数唯一性高的场景。 它是 @lru_cache(maxsize=None) 的简化版,功能单一但使用更简洁。 使用时需注意内存占用和参数类型,确保函数是“纯”的(无副作用)。 对于需要缓存大小控制的场景或更复杂的缓存管理,应使用 lru_cache。 以上为个人经验,希望能给大家一个参考,也希望大家多多支持风君子博客。 您可能感兴趣的文章: Python中@property与@cached_property的实现 Python中的@cache巧妙用法 Python中十个常用的自定义装饰器的使用详解 Python如何定义一个能接收可选参数的装饰器 Python中多个装饰器执行顺序验证深入讲解 Python中的闭包装饰器和深浅拷贝案例演示 Python装饰器中常用的functools.wraps的使用 Python中函数的闭包和装饰器示例详解
  • 目录
    • 一、@cache装饰器的基本概念
    • 二、工作原理
    • 三、使用示例
    • 四、注意事项
    • 五、@cache与@lru_cache的区别
    • 六、总结

    @cache 是 Python 3.9 引入的新功能,来源于标准库 functools 模块。它的作用是 对函数结果进行缓存(记忆化 memoization),从而避免重复计算,提高程序性能。

    它的定义方式非常简单:

    from functools import cache
    
    @cache
    def some_function(...):
        ...
    

    当你用 @cache 修饰一个函数时,Python 会将该函数的输入参数与计算结果自动保存到一个缓存(字典)中。当后续调用该函数且参数完全相同时,不会再次执行函数体的计算逻辑,而是直接返回之前缓存的结果。

    @cache 装饰器内部其实是基于 functools.lru_cache 实现的,它等价于:

    from functools import lru_cache
    
    cache = lru_cache(maxsize=None)
    

    也就是说:

    • 无限大小缓存maxsize=None 表示缓存结果没有数量限制,会根据需要一直增长(直到你的内存允许)。
    • 键值匹配:缓存根据参数 判断是否命中(必须是可哈希类型,如数字、字符串、元组等)。
    • 返回缓存结果:命中缓存时,直接返回结果而不执行函数计算。

    1. 基本示例:递归斐波那契数列

    from functools import cache
    
    @cache
    def fib(n):
        print(f"计算 fib({n})")
        if n < 2:
            return n
        return fib(n - 1) + fib(n - 2)
    
    print(fib(10))  # 第一次需要计算
    print(fib(10))  # 第二次直接命中缓存,不会重新计算
    

    运行效果:

    • 第一次调用会完整计算 fib(10),输出多行 "计算 fib(n)" 的提示信息。
    • 第二次调用相同参数,直接返回缓存值,不输出任何计算日志。

    2. 模拟耗时计算

    import time
    from functools import cache
    
    @cache
    def slow_function(x):
        print(f"开始计算 {x}...")
        time.sleep(2)  # 模拟耗时
        return x * x
    
    # 首次调用耗时
    print(slow_function(5))
    
    # 第二次调用相同参数时几乎立即返回
    print(slow_function(5))
    

    在实际场景中,如果一个函数计算代价高(如数据库查询、大文件解析、复杂计算等),使用 @cache 能显著减少重复工作。

    适用场景

    • 适合纯函数(函数结果只依赖输入参数,且不会产生副作用)。
    • 不适合需要每次实时更新的函数(例如获取当前时间、外部数据接口)。

    参数限制

    • 参数必须可哈希(hashable),如整数、字符串、元组等。
    • 如果传入不可哈希类型(如列表、字典),会报错 TypeError: unhashable type

    内存占用

    • @cache 默认缓存无限大小,可能造成内存占用增加;如果希望限制缓存大小,应使用 lru_cache(maxsize=...) 来控制。

    缓存失效

    • @cache 没有内置超时或自动失效机制,缓存会一直保留直到程序结束或手动清除:
    your_function.cache_clear()
    

    特性 @cache @lru_cache
    缓存大小限制 无限 (maxsize=None) 可自定义 maxsize
    缓存策略 简单字典保存 LRU(Least Recently Used)淘汰
    用途 适合始终命中缓存且参数种类有限 适合缓存有限结果并自动淘汰旧数据

    • @cache 能让函数的重复调用变得快速,尤其适合计算昂贵且参数唯一性高的场景。
    • 它是 @lru_cache(maxsize=None) 的简化版,功能单一但使用更简洁。
    • 使用时需注意内存占用和参数类型,确保函数是“纯”的(无副作用)。
    • 对于需要缓存大小控制的场景或更复杂的缓存管理,应使用 lru_cache

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持风君子博客。

    您可能感兴趣的文章:

    • Python中@property与@cached_property的实现
    • Python中的@cache巧妙用法
    • Python中十个常用的自定义装饰器的使用详解
    • Python如何定义一个能接收可选参数的装饰器
    • Python中多个装饰器执行顺序验证深入讲解
    • Python中的闭包装饰器和深浅拷贝案例演示
    • Python装饰器中常用的functools.wraps的使用
    • Python中函数的闭包和装饰器示例详解

    站内搜索