能否在Python类方法中使用cached_property?两种场景分析
Python中classmethod与cached_property的调用问题分析
先看用户提供的示例代码:
class MyClass: @classmethod def some_command(cls) -> int: result = cls.slow_but_always_the_same_result_calculation() # :) ... @cached_property def slow_but_always_the_same_result_calculation(self): ... # Do the slow calculation return result
下面分两种场景逐一分析:
场景1:直接类调用
import MyClass MyClass.some_command()
这种调用完全不可行,会直接抛出TypeError: 'cached_property' object is not callable。
原因:@cached_property是绑定实例的装饰器,本质是一个描述器——当通过实例访问被装饰的方法时,它会自动执行计算并缓存结果;但通过类访问时,返回的是cached_property装饰器对象本身,而非可调用的方法。因此cls.slow_but_always_the_same_result_calculation()相当于试图调用一个非可调用对象,直接触发报错,result根本无法被赋值。
场景2:实例调用
import MyClass my_class_instance = MyClass() my_class_instance.some_command()
这种调用同样会报错,错误信息和场景1完全一致。
原因:类方法some_command的第一个参数cls始终指向类本身(无论通过类还是实例调用类方法),所以代码里的cls.slow_but_always_the_same_result_calculation()本质还是通过类访问装饰器对象,同样无法调用,自然也无法拿到计算结果。
补充:正确的用法思路
如果想让类方法复用这个“慢但结果固定”的计算逻辑,有两种常见方案:
- 将计算方法改为类方法,并用
functools.lru_cache实现类级别的缓存:from functools import lru_cache class MyClass: @classmethod def some_command(cls) -> int: result = cls.slow_but_always_the_same_result_calculation() ... @classmethod @lru_cache(maxsize=None) def slow_but_always_the_same_result_calculation(cls): ... # 慢计算逻辑 return result - 在类方法内创建实例,通过实例访问
cached_property属性(适合计算结果与实例无关的场景):class MyClass: @classmethod def some_command(cls) -> int: instance = cls() result = instance.slow_but_always_the_same_result_calculation ... @cached_property def slow_but_always_the_same_result_calculation(self): ... # 慢计算逻辑 return result
内容的提问来源于stack exchange,提问作者Slav Kirilov
相关产品推荐
相关产品推荐

