只计算一次属性并多次使用结果(不同的方法)

Posted

技术标签:

【中文标题】只计算一次属性并多次使用结果(不同的方法)【英文标题】:Calculate property only once and use the result several times (different approaches) 【发布时间】:2017-12-18 19:06:50 【问题描述】:

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

我看到以下选项。你认为哪个是正确的,还是更 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

【问题讨论】:

好问题。 Related SO question 强烈支持 lru_cache。因为你不使用任何参数,直觉上,我会继续使用普通的 try-catch。 这能回答你的问题吗? Caching class attributes in Python 【参考方案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】:

    Try/except 简单易读,但总有一天你会想要缓存另一个属性,对吧?所以有一天你可能会编写自己的缓存属性。

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

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

【讨论】:

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

以上是关于只计算一次属性并多次使用结果(不同的方法)的主要内容,如果未能解决你的问题,请参考以下文章

vue计算属性computed和监视器watch的使用

Linq:按计算结果过滤并重用此结果

Vue计算属性computed:

sql UPDATE,一个计算用了多次,能不能只计算一次?

computed之计算属性

ajax多次请求,只执行最后一次的方法