{"id":840,"library":"cached-property","title":"Cached Property","description":"cached-property (current version 2.0.1) is a Python decorator for caching the results of properties in classes. It provides a straightforward way to memoize expensive computations, executing them only once per instance and storing the result as a regular attribute. The library offers basic, thread-safe, and time-based (TTL) caching mechanisms, as well as experimental async/await compatibility. It maintains an active development status with releases typically aligned with Python version support updates.","status":"active","version":"2.0.1","language":"python","source_language":"en","source_url":"https://github.com/pydanny/cached-property","tags":["caching","decorator","performance","property","memoization"],"install":[{"cmd":"pip install cached-property","lang":"bash","label":"Install latest version"}],"dependencies":[],"imports":[{"symbol":"cached_property","correct":"from cached_property import cached_property"},{"symbol":"threaded_cached_property","correct":"from cached_property import threaded_cached_property"},{"symbol":"cached_property_with_ttl","correct":"from cached_property import cached_property_with_ttl"},{"symbol":"threaded_cached_property_with_ttl","correct":"from cached_property import threaded_cached_property_with_ttl"}],"quickstart":{"code":"from cached_property import cached_property\n\nclass Monopoly:\n    def __init__(self):\n        self.boardwalk_price = 500\n\n    @cached_property\n    def boardwalk(self):\n        # In reality, this might represent a database call or time\n        # intensive task like calling a third-party API.\n        self.boardwalk_price += 50\n        return self.boardwalk_price\n\nmonopoly = Monopoly()\nprint(f\"First access: {monopoly.boardwalk}\")\nprint(f\"Second access (cached): {monopoly.boardwalk}\")\n\n# To invalidate the cache, delete the attribute:\ndel monopoly.__dict__['boardwalk'] # Or del monopoly.boardwalk for simple cases\nprint(f\"After invalidation: {monopoly.boardwalk}\")","lang":"python","description":"This example demonstrates how to use the `cached_property` decorator to cache an expensive property computation. The `boardwalk` property will only execute its logic once per instance, returning the cached value on subsequent accesses until explicitly invalidated."},"warnings":[{"fix":"Upgrade your Python environment to 3.8+ or pin `cached-property` to a compatible version (e.g., `cached-property<2.0.0` for Python <3.8).","message":"Version 2.0.0 of `cached-property` officially dropped support for Python versions older than 3.8. Users on Python 2.7 or 3.7 and below should stick to `cached-property` version 1.5.2 or earlier.","severity":"breaking","affected_versions":"<2.0.0"},{"fix":"For basic caching in Python 3.8+, consider using `from functools import cached_property`. If you require TTL or explicit thread-safe caching, `cached-property` remains a viable choice.","message":"Python 3.8+ introduced `functools.cached_property` into the standard library. For basic property caching in Python 3.8+, `functools.cached_property` is generally preferred. `cached-property` provides additional features like time-to-live (TTL) and thread-safe variants that are not present in `functools.cached_property`.","severity":"gotcha","affected_versions":"2.0.0+"},{"fix":"Be aware of this limitation when using TTL features. If immediate invalidation is critical, consider using the base `cached_property` and managing invalidation manually (`del obj.property_name`) or designing around the TTL expiration.","message":"The `cached_property_with_ttl` and `threaded_cached_property_with_ttl` functions do not reliably allow manual invalidation of the cache. This means that once a value is cached with a TTL, it might not be possible to force a re-computation before the TTL expires.","severity":"gotcha","affected_versions":"1.0.0+"},{"fix":"Avoid mixing `asyncio` with threading if possible. If necessary, ensure proper synchronization and careful management of event loops across threads to prevent data corruption or incorrect cached values.","message":"When combining `asyncio` with threading, especially with the `ttl` versions, be aware that most `asyncio` objects are not thread-safe. Running separate event loops in different threads can lead to unexpected behavior with cached values.","severity":"gotcha","affected_versions":"1.0.0+"},{"fix":"Prefer `del obj.property_name` for simple cache invalidation. Ensure your application logic correctly triggers invalidation when the underlying data changes, as the decorator itself does not automatically detect state changes.","message":"Invalidating a `cached_property` is typically done by deleting the attribute (`del obj.property_name`). The library's quickstart sometimes shows `del obj.__dict__['property_name']` which is equivalent but can be less idiomatic. Both methods clear the cached value, allowing the property method to run again on next access.","severity":"gotcha","affected_versions":"1.0.0+"}],"env_vars":null,"last_verified":"2026-05-12T20:17:45.423Z","next_check":"2026-06-27T00:00:00.000Z","problems":[{"fix":"To use the `cached-property` library (version 2.0.1 requires Python 3.8+), ensure it's installed (`pip install cached-property`) and import it directly: `from cached_property import cached_property`. If you specifically intend to use the standard library `functools.cached_property`, ensure your Python environment is version 3.8 or newer.","cause":"This error occurs when attempting to import `cached_property` from Python's built-in `functools` module in a Python version prior to 3.8, where it was not yet available, or when confusing the standard library `cached_property` with the external `cached-property` package.","error":"ImportError: cannot import name 'cached_property' from 'functools'"},{"fix":"If you need a writable property with caching, you typically manage cache invalidation manually within a custom setter (e.g., `del self.__dict__['my_property']`) or by defining a standard `@property` with a `@my_property.setter` and implementing explicit caching logic there.","cause":"The `cached_property` decorator (both from the external `cached-property` library and `functools`) is designed for properties whose values are computed once and then cached as effectively immutable attributes; it does not inherently support the `.setter` method like a standard `property` decorator.","error":"AttributeError: 'cached_property' object has no attribute 'setter'"},{"fix":"To use `cached_property` with `__slots__`, you must include `'__dict__'` in your `__slots__` definition (e.g., `__slots__ = ('my_attribute', '__dict__')`) to provide a mutable dictionary for caching. Alternatively, avoid `__slots__` if memory optimization is not critical, or consider using `functools.lru_cache` on a regular method if applicable.","cause":"This error commonly arises when `cached_property` is used with classes that define `__slots__` but do not include `'__dict__'` in their `__slots__` definition. `cached_property` relies on writing the cached value to the instance's `__dict__`, which is unavailable or immutable in such cases.","error":"TypeError: Cannot use cached_property instance without calling __set_name__ on it."},{"fix":"For thread-safe caching with the `cached-property` library, use the `threaded_cached_property` decorator (`from cached_property import threaded_cached_property`). If you were relying on the removed `functools.cached_property` lock, you must implement explicit locking within your getter function or around access points to ensure thread synchronization.","cause":"This error specifically occurs in Python 3.12 and later versions when code attempts to access an undocumented `lock` attribute on a `cached_property` instance. The internal, class-wide locking mechanism of `functools.cached_property` (which caused performance issues) was removed in Python 3.12.","error":"AttributeError: 'cached_property' object has no attribute 'lock'"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":null,"quickstart_tag":null,"pypi_latest":"2.0.1","cli_name":"","install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","installed_version":"2.0.1","pypi_latest":"2.0.1","is_stale":false,"results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"cached-property","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.09,"mem_mb":4,"disk_size":"17.8M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"cached-property","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.08,"mem_mb":4,"disk_size":"17.8M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"cached-property","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.5,"import_time_s":0.06,"mem_mb":4,"disk_size":"18M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"cached-property","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.06,"mem_mb":4,"disk_size":"18M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"cached-property","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.17,"mem_mb":4.9,"disk_size":"19.6M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"cached-property","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.17,"mem_mb":4.9,"disk_size":"19.6M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"cached-property","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.6,"import_time_s":0.13,"mem_mb":4.9,"disk_size":"20M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"cached-property","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.13,"mem_mb":4.9,"disk_size":"20M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"cached-property","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.34,"mem_mb":8.2,"disk_size":"11.5M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"cached-property","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.38,"mem_mb":8.2,"disk_size":"11.5M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"cached-property","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.5,"import_time_s":0.32,"mem_mb":8.2,"disk_size":"12M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"cached-property","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.34,"mem_mb":8.2,"disk_size":"12M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"cached-property","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.36,"mem_mb":8.7,"disk_size":"11.3M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"cached-property","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.41,"mem_mb":8.7,"disk_size":"11.1M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"cached-property","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.5,"import_time_s":0.31,"mem_mb":8.7,"disk_size":"12M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"cached-property","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.33,"mem_mb":8.7,"disk_size":"12M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"cached-property","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.08,"mem_mb":3.9,"disk_size":"17.3M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"cached-property","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.08,"mem_mb":3.9,"disk_size":"17.3M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"cached-property","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":1.7,"import_time_s":0.06,"mem_mb":3.9,"disk_size":"18M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"cached-property","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.07,"mem_mb":3.9,"disk_size":"18M"}]},"quickstart_checks":{"last_tested":"2026-04-24","tag":null,"tag_description":null,"results":[{"runtime":"python:3.10-alpine","exit_code":0},{"runtime":"python:3.10-slim","exit_code":0},{"runtime":"python:3.11-alpine","exit_code":0},{"runtime":"python:3.11-slim","exit_code":0},{"runtime":"python:3.12-alpine","exit_code":0},{"runtime":"python:3.12-slim","exit_code":0},{"runtime":"python:3.13-alpine","exit_code":0},{"runtime":"python:3.13-slim","exit_code":0},{"runtime":"python:3.9-alpine","exit_code":0},{"runtime":"python:3.9-slim","exit_code":0}]}}