When to use @cached_property over @property @cache?


I’m adding an invariant computed property to an “immutable” dataclass.

After reading the documentation of the @functools.cached_property it’s not clear to me which approach is preferred for my case: @cached_property or @property @cache.

The documentation isn’t making a claim about what should be done, but what can be done. If using @property (potentially with some other caching decorator), you cannot set the attribute (without a setter).

The reason the documentation needs to point this out is because otherwise users may assume that @cached_property has the exact same semantics as @property, which is not the case.

It sounds like you probably just want to use @cached_property.

(Also for what it’s worth, I find the semantics of @cache on methods is easy to get confused about, e.g. you end up with a class-wide cache instead of an instance-wide cache)

1 Like

*reworded the question

The way I read the documentation: use @property @cached unless you want the users of the class to mutate and reset the cache.

But how “similar” is similar? Are there any other implementation-detail side effects that are ommited from the current documentation, e.g. @cached_property being somehow “faster”?

unless you want the users of the class to mutate and reset the cache

Python follows the philosophy of “consenting adults”. It’s possible for users to reset the cache with @property + @cache as well. In both cases, users have to go out of their way to do it.

Yes, like I said, you’d probably end up with a class-level cache instead of an instance-level cache, which in my opinion is usually not what you want. cached_property is much faster, but you’d need to benchmark to know how much faster for your use case (e.g. does your class implement a custom __hash__).

Indeed, that’s the case.

Another side effect mentioned in the FAQ (and the doc for @lru_cache: @property @cache will keep the instance alive.