【问题标题】:Calculate property only once and use the result several times (different approaches)只计算一次属性并多次使用结果(不同的方法)
【发布时间】:2025-12-08 21:10:02
【问题描述】:

我尝试多次使用类方法的结果,而不进行获得结果所需的繁重计算。

我看到以下选项。你认为哪个是正确的,还是更 Pythonic?

各有什么优缺点?

尝试/排除方法

class Test:
    def __init__(self, *args):
        # do stuff

    @property
    def new_method(self):
        try:
            return self._new_property
        except AttributeError:
            # do some heavy calculations
            return self._new_property

lru_cache 方法

from functools import lru_cache

class Test:
    def __init__(self, *args):
        # do stuff

    @property
    @lru_cache()
    def new_method(self):
        # do some heavy calculations
        return self._new_property

Django 的 cache_property 方法

from django.utils.functional import cached_property

class Test:
    def __init__(self, *args):
        # do stuff

    @cached_property
    def new_method(self):
        # do some heavy calculations
        return self._new_property

【问题讨论】:

标签: python properties class-method


【解决方案1】:

Python 3.8 更新:您现在可以使用functools.cached_property

from functools import cached_property

class Test:
    def __init__(self, *args):
        # do stuff

    @cached_property
    def new_method(self):
        # do some heavy calculations
        return self._new_property

【讨论】:

    【解决方案2】:
    1. Try/except 简单易读,但总有一天你会想要缓存另一个属性,对吧?所以有一天你可能会编写自己的缓存属性。

    2. lru_cache 使用标准库是个好主意,但由于您不需要 lru 缓存,因此可能会产生开销。

    3. Django 的 cache_property 完全按照您的意愿工作,而且非常简单。它在 werkzeug 中具有类似功能(因此 Flask 用户也熟悉它),很容易找到来源,所以它可能是您的不错选择。

    【讨论】:

    • 是的,Django的cache_property很简单。我做了一些测试,它的速度非常快,比 try/except 快 2.5。如果使用它没有缺点,我想我会使用它。我的班级有几个属性,也许代码会更干净。