使用cached_property构造在python中缓存属性

时间:2017-10-03 07:31:25

标签: python caching properties

最近我看到在python第三方软件包的一些代码库中使用cached_properties装饰器,如celery和django(它也是Django中的实用程序函数)和瓶子web框架。还有一个独立的包使用cached_properties。 据我所知,它通过提供缓存行为来避免繁重的计算。

以下是实施cached_property

的源代码
class cached_property(object):
    """
    A property that is only computed once per instance and then replaces itself
    with an ordinary attribute. Deleting the attribute resets the property."""

    def __init__(self, func):
        self.__doc__ = getattr(func, '__doc__')
        self.func = func

    def __get__(self, obj, cls):
        if obj is None:
            return self
        value = obj.__dict__[self.func.__name__] = self.func(obj)
        return value

这就是它的用法:

class Monopoly(object):

    def __init__(self):
        self.boardwalk_price = 500

    @cached_property
    def boardwalk(self):
        # Again, this is a silly example. Don't worry about it, this is
        #   just an example for clarity.
        self.boardwalk_price += 50
        return self.boardwalk_price

现在,当我们运行它时,价格保持在550美元。

>>> monopoly = Monopoly()
>>> monopoly.boardwalk
550
>>> monopoly.boardwalk
550
>>> monopoly.boardwalk
550

我们只是将第一次调用的结果存储到属性/属性中,以后再使用它来避免重新计算?我确信这是一个非常愚蠢的问题,但我在这里错过了什么?

例如:

monopoly = Monopoly()
>>> stored_value = monopoly.boardwalk
550

# now use stored_value instead of making a call to `monopoly.boardwalk`.

1 个答案:

答案 0 :(得分:1)

当然可以,但是如果许多不同的地方使用monopoly.boardwalk怎么办?现在,您必须确保所有这些位置在本地缓存值。 你可以让Monopoly类负责缓存。

cached_property可以让类变得容易,而不是属性的使用者。

如果你正在努力寻找在许多不同地方使用的东西的例子:在一个体积适中的Django应用程序中你有模板,视图和后端代码都可能触及给定的模型。其中一些地方本身就是Django框架(比如管理界面),当你向模型中添加昂贵的操作时更新所有这些地方是不切实际的。使用装饰器实用的;把责任放在模型中可以使所有其他代码更简单。