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

为类使用lru_cache后,类方法清除缓存报错的问题咨询

类实例缓存与自定义清除方法的问题解决

当类的构造逻辑复杂且实例内容不会变化时,用functools.lru_cache装饰类可以高效缓存实例,但尝试在类中定义classmethod来实现缓存清除(同时处理文件缓存)时,会遇到'classmethod' object is not callable的错误。

以下是最小复现示例:

from functools import lru_cache
        
@lru_cache(maxsize=None)
class MyClass:
    def __init__(self, x):
        print(f"Initializing with {x}")
        self.x = x

    @classmethod
    def clear(cls):
        print('clearing cache')
        cls.cache_clear()

a = MyClass(1)
b = MyClass(1)
print(a is b)  # 输出True
try: MyClass.clear()
except Exception as e: print(e)  # 报错:'classmethod' object is not callable
# 直接调用 MyClass.cache_clear() 可以正常清除缓存
c = MyClass(1)

问题原因

用lru_cache装饰类后,原来的类被包裹成了一个缓存函数,此时MyClass指向的是这个缓存函数而非原类。原类中定义的classmethod并没有被正确绑定到外层的缓存函数上,直接调用MyClass.clear()时,访问到的是原类的classmethod对象,而非可调用的绑定方法,因此触发错误。

解决方案

方案1:装饰后手动绑定清除方法

先定义类,再用lru_cache装饰,之后手动给缓存后的对象添加清除方法:

from functools import lru_cache

class MyClass:
    def __init__(self, x):
        print(f"Initializing with {x}")
        self.x = x

# 用lru_cache装饰类
MyClass = lru_cache(maxsize=None)(MyClass)

# 定义清除方法并绑定到缓存后的对象
@classmethod
def clear(cls):
    print('clearing cache')
    cls.cache_clear()
    # 在这里添加清除文件缓存的逻辑
    print('clearing file cache')

MyClass.clear = clear

测试验证:

a = MyClass(1)
b = MyClass(1)
print(a is b)  # 输出True
MyClass.clear()  # 正常打印缓存和文件缓存清除信息
c = MyClass(1)  # 重新初始化,打印Initializing with 1

方案2:用工厂方法封装缓存逻辑

不直接装饰类,而是给类的工厂方法添加lru_cache,保持类本身的结构完整性:

from functools import lru_cache

class MyClass:
    def __init__(self, x):
        print(f"Initializing with {x}")
        self.x = x

    @classmethod
    @lru_cache(maxsize=None)
    def get_instance(cls, x):
        """工厂方法,返回缓存后的实例"""
        return cls(x)

    @classmethod
    def clear(cls):
        print('clearing cache')
        cls.get_instance.cache_clear()
        # 在这里添加清除文件缓存的逻辑
        print('clearing file cache')

使用方式:

a = MyClass.get_instance(1)
b = MyClass.get_instance(1)
print(a is b)  # 输出True
MyClass.clear()  # 正常执行清除逻辑
c = MyClass.get_instance(1)  # 重新初始化实例

方案对比

  • 方案1:保持了原有的MyClass(x)调用方式,无需修改实例创建代码,但需要手动绑定方法,稍显繁琐。
  • 方案2:符合类的设计规范,缓存逻辑封装在工厂方法中,类结构更清晰,推荐用于复杂场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 21:05:04