You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中@cached_property与@lru_cache装饰器的区别及适用场景

Hey there! As someone who’s spent plenty of time tinkering with Django and Python’s standard library, I totally get why these two decorators might feel confusing at first. Let’s break down their differences, use cases, and examples so you can pick the right one for your code.

@cached_property vs @lru_cache: Key Differences

1. Origin & Core Purpose

  • @cached_property is a Django-specific decorator (found in django.utils.functional) built exclusively for class instance properties. It’s designed to cache expensive-to-calculate values that are tied directly to an individual instance’s state.
  • @lru_cache is part of Python’s native functools module—it’s a general-purpose caching tool that works with any function or method (not just instance properties). It uses a least-recently-used algorithm to limit cache size if you specify a maxsize.

2. Cache Key Logic

  • @cached_property uses the instance itself as the implicit cache key. Each instance gets its own unique cache for the property—so two different instances of the same class will never share cached values, which is ideal for instance-specific data.
  • @lru_cache generates keys based on the arguments passed to the function/method. For instance methods, this includes the self parameter, so different instances get separate cached entries for the same input arguments. For static/class methods or plain functions, keys are based solely on input parameters.

3. Memory Lifecycle

  • @cached_property stores its cache directly on the instance. When the instance is garbage-collected (no longer referenced), the cached value is automatically cleaned up too—no risk of leftover cache cluttering memory.
  • @lru_cache ties its cache to the function/method itself, not the instance. Cached values stick around until you manually call cache_clear() or the cache hits its maxsize limit. Using it on short-lived instances can lead to unnecessary memory bloat if not managed carefully.

4. Access Pattern

  • With @cached_property, you access the value like a regular class attribute—no parentheses needed. For example: my_instance.my_cached_property.
  • With @lru_cache, even for instance methods, you still call it like a function: my_instance.my_cached_method(arg1, arg2).
When to Use Which?

Choose @cached_property If:

  • You’re working with Django model instances or any class where the cached value is unique to each instance.
  • You want the cache to automatically disappear when the instance is deleted.
  • You prefer accessing the value like a standard attribute (no parentheses).
  • The computation depends on the instance’s state (e.g., aggregating related model data).

Choose @lru_cache If:

  • You’re caching a pure function (same inputs always produce the same output, no side effects).
  • You need to cache static/class methods or standalone utility functions.
  • You want to control the maximum cache size to limit memory usage.
  • You need to manually clear the cache occasionally (using cache_clear()).
Practical Examples

Example 1: @cached_property in a Django Model

Suppose you have an Order model and want to calculate the total amount by summing related OrderItem prices. This is a perfect fit for @cached_property:

from django.db import models
from django.utils.functional import cached_property

class Order(models.Model):
    customer = models.ForeignKey("Customer", on_delete=models.CASCADE)

    @cached_property
    def total_amount(self):
        # Calculate once per instance, cache the result
        total = self.orderitem_set.aggregate(total=models.Sum("price"))["total"]
        return total if total is not None else 0

# Usage
order = Order.objects.get(id=1)
print(order.total_amount)  # Runs calculation + DB query once
print(order.total_amount)  # Returns cached value instantly, no DB hit

Example 2: @lru_cache for a Utility Function

For a heavy computation with repeatable inputs, @lru_cache eliminates redundant work:

from functools import lru_cache

@lru_cache(maxsize=128)  # Limit cache to 128 most recent entries
def calculate_fibonacci(n):
    if n <= 1:
        return n
    return calculate_fibonacci(n-1) + calculate_fibonacci(n-2)

# Usage
calculate_fibonacci(20)  # Computes and caches intermediate values
calculate_fibonacci(20)  # Returns cached result immediately
calculate_fibonacci.cache_clear()  # Manually reset the cache if needed

Example 3: @lru_cache on a Class Method

For class-level logic that doesn’t depend on instance state, @lru_cache works great:

from functools import lru_cache

class NumberUtils:
    @classmethod
    @lru_cache(maxsize=64)
    def is_prime(cls, num):
        if num <= 1:
            return False
        for i in range(2, int(num ** 0.5) + 1):
            if num % i == 0:
                return False
        return True

# Usage
NumberUtils.is_prime(97)  # Computes once, caches result
NumberUtils.is_prime(97)  # Uses cached value

内容的提问来源于stack exchange,提问作者Roushan Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:29:48