Use cached_property only for stable instance state
functools.cached_property turns an instance method into a value computed on first lookup and then stored on that instance. It is a good fit when the inputs to the calculation are effectively immutable for the instance’s lifetime. This example copies incoming measurements into a tuple, so later changes to the caller’s list cannot silently change the report’s internal state.
The first read of report.total runs the method, increments computations, and returns 12. The second read returns the attribute cached on report; it does not invoke the method again. The assertions establish those facts for this particular object and input. They do not measure performance or prove that caching is appropriate for every derived value.
Avoid this decorator for a value that should automatically follow mutable fields. If _measurements were changed after total had been cached, the old value would remain until code explicitly deleted report.total or assigned a replacement. The standard documentation also notes that a cached property can run more than once under concurrent access, so a getter with non-idempotent effects needs its own synchronization.
cached_property was added in Python 3.8; Python 3.12 removed its former undocumented per-property lock. See the official cached_property documentation.
AI assistance disclosure: this article was drafted with AI assistance and the example was designed as a synthetic, deterministic demonstration.
from functools import cached_property
class Report:
def __init__(self, measurements):
self._measurements = tuple(measurements)
self.computations = 0
@cached_property
def total(self):
self.computations += 1
return sum(self._measurements)
raw = [3, 4, 5]
report = Report(raw)
raw.append(100)
assert report.total == 12
assert report.total == 12
assert report.computations == 1
print(f"total={report.total}, computations={report.computations}")
total=12, computations=1
Comments
Post a Comment