You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为依赖类属性的Python类方法配置lru_cache?

问题分析

你的问题出在lru_cache对类方法的缓存逻辑上:@classmethod修饰的test方法被缓存时,缓存的键是(cls, x),但类对象cls的哈希值不会随类属性a的变化而改变。所以即使你修改了Test.a,lru_cache依然会返回之前基于旧a值计算的缓存结果,导致输出不符合预期。

方案1:a变更时清空缓存(推荐,适配a极少变更的场景)

既然a极少变更,最简单的方式就是在修改a时直接清空test方法的缓存,后续调用会自动重新计算新a值对应的结果。只需在__new__方法中添加缓存清空逻辑:

from functools import lru_cache

class Test():
    a = 1

    def __new__(cls, a = 1):
        cls.a = a
        cls.test.cache_clear()  # 变更a时清空缓存
        return super().__new__(cls)
    
    @classmethod
    @lru_cache(maxsize=32)
    def test(cls, x):
        return x * cls.a

print(Test.test(1), Test(2).test(1), Test.test(1))  # 输出:1 2 2

优点:实现简单,完全符合你要求的调用方式,无需修改test方法的参数结构,适配a极少变更的场景。

方案2:将a纳入缓存键(保留所有(a,x)组合的缓存)

如果需要保留不同a值对应的缓存结果(即使a变更后也不丢弃旧缓存),可以自定义装饰器,自动将类属性a作为缓存键的一部分传入:

from functools import lru_cache, wraps

def lru_cache_with_attr(attr_name):
    def decorator(func):
        @wraps(func)
        def wrapper(cls, *args, **kwargs):
            # 将指定类属性作为额外参数传入缓存函数
            return cached_func(cls, getattr(cls, attr_name), *args, **kwargs)
        
        @lru_cache(maxsize=32)
        def cached_func(cls, attr_val, *args, **kwargs):
            return func(cls, *args, **kwargs)
        
        return wrapper
    return decorator

class Test():
    a = 1

    def __new__(cls, a = 1):
        cls.a = a
        return super().__new__(cls)
    
    @classmethod
    @lru_cache_with_attr('a')
    def test(cls, x):
        return x * cls.a

print(Test.test(1), Test(2).test(1), Test.test(1))  # 输出:1 2 2

优点:保留所有(a,x)组合的缓存结果,后续切换回旧a值时可直接复用缓存;缺点:实现相对复杂,缓存占用会随a的不同值增加。

内容的提问来源于stack exchange,提问作者André

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 12:26:02