为类使用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
相关产品推荐
相关产品推荐

