探索 Python 的 functools: 缓存、缓存属性和 LRU 缓存

Python 的 functools 模块是功能编程爱好者的宝藏,提供了使代码更高效和优雅的工具。在这篇文章中,我们将深入探讨三个强大的函数——cachecached_propertylru_cache——它们通过存储昂贵计算的结果来帮助优化性能。无论是加速递归算法还是简化基于类的计算,这些工具都能满足你的需求。让我们通过清晰的解释和实际的例子来探索每一个工具。

1. cache: 简单的无界备忘录

cache 装饰器是一种轻量级的方式来备忘函数结果,当相同的输入再次出现时存储它们以供重用。它就像是你函数输出的便签——无需重新计算!

工作原理
  • 功能:在一个无限制的字典中存储函数结果,使用参数作为键。
  • 使用时机:适用于计算开销大的纯函数(相同输入,相同输出)。
  • 主要特点:它等同于 lru_cache(maxsize=None),但由于其简单性而更快。

示例

from functools import cache

@cache
def factorial(n):
    return n * factorial(n-1) if n else 1

print(factorial(10))  # 计算结果:3628800

print(factorial(10))  # 返回缓存结果,无需重新计算
为什么它很棒
  • 速度:避免冗余计算,使得像阶乘这样的递归函数速度极快。
  • 简单性:无需配置——只需添加装饰器即可。
  • 警告:缓存会无限增长,因此对于具有许多唯一输入的函数,请监控内存使用情况。

 

2. cached_property: 一次性属性计算

cached_property 装饰器将类方法转换为一个属性,该属性只计算一次其值并为实例缓存该值。可以将其视为一个懒加载的属性,它会一直存在。

工作原理
  • 它的作用:第一次访问时运行该方法,将结果缓存为实例属性,并在后续调用中返回缓存的值。
  • 何时使用:非常适合在第一次计算后不会改变的类中的昂贵计算。
    关键特性:仅适用于实例方法(需要 self)。

示例

from functools import cached_property

class Circle:
    def __init__(self, radius):
        self.radius = radius

    @cached_property

    def area(self):
        print("计算面积")
        return 3.14159 * self.radius ** 2

c = Circle(5)
print(c.area)  # 输出: 计算面积,然后 78.53975
print(c.area)  # 输出: 78.53975(缓存,无需重新计算)

为什么它很棒

 

3. lru_cache:灵活的、有界的记忆化

lru_cache装饰器是记忆化的强力工具,提供可配置大小的最近最少使用(LRU)缓存。它是线程安全的,并且具有丰富的反射特性,使其成为优化复杂函数的首选。

 

它是如何工作的

 

示例

from functools import lru_cache

@lru_cache(maxsize=32)
def fib(n):
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)

print(fib(10))  # 计算结果:55
print(fib.cache_info())  # 显示: CacheInfo(hits=8, misses=11, maxsize=32, currsize=11)

 

为什么它很棒

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注