Zope Cache Descriptors

6.0 · active · verified Fri Apr 17

Zope Cache Descriptors is a Python library from the Zope Foundation providing `cached` method and `CachedProperty` decorators for easy result caching. It's currently at version 6.0, supports Python 3.9+, and sees active maintenance with releases roughly aligning with major Python version support cycles. It's designed for simple, in-memory caching of computation results.

Common errors

Warnings

Install

Imports

Quickstart

Demonstrates basic usage of `CachedProperty` and `cached` decorators, including how to access cached values and perform explicit invalidation for both properties and methods. Note the distinct invalidation patterns for each.

from zope.cachedescriptors.property import CachedProperty
from zope.cachedescriptors.method import cached
import time

class DataFetcher:
    def __init__(self, id_val):
        self.id = id_val
        self._fetch_count = 0

    @CachedProperty
    def expensive_property(self):
        self._fetch_count += 1
        print(f"  [Property] Fetching data for {self.id}... (call {self._fetch_count})")
        time.sleep(0.1) # Simulate network delay
        return f"Data for {self.id}-{time.time()}"

    @cached
    def expensive_method(self, param):
        self._fetch_count += 1
        print(f"  [Method] Fetching data for {self.id} with param {param}... (call {self._fetch_count})")
        time.sleep(0.1) # Simulate network delay
        return f"Result for {self.id}-{param}-{time.time()}"

# Example Usage
fetcher = DataFetcher("user123")

print("--- CachedProperty Demo ---")
result1 = fetcher.expensive_property
print(f"Property 1: {result1}")
result2 = fetcher.expensive_property # Should be cached
print(f"Property 2: {result2}")
assert result1 == result2

# Invalidate the property cache by deleting the attribute
del fetcher.expensive_property
result3 = fetcher.expensive_property # Should re-calculate
print(f"Property 3 (after invalidation): {result3}")
assert result1 != result3

print("\n--- CachedMethod Demo ---")
method_result1 = fetcher.expensive_method("report_a")
print(f"Method 1: {method_result1}")
method_result2 = fetcher.expensive_method("report_a") # Should be cached
print(f"Method 2: {method_result2}")
assert method_result1 == method_result2

# Invalidate a specific method call with arguments
fetcher.expensive_method.invalidate(fetcher, "report_a")
method_result3 = fetcher.expensive_method("report_a") # Should re-calculate
print(f"Method 3 (after invalidation): {method_result3}")
assert method_result1 != method_result3

method_result4 = fetcher.expensive_method("report_b") # New argument, new cache entry
print(f"Method 4: {method_result4}")

view raw JSON →