最近我看到在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`.
答案 0 :(得分:1)
当然可以,但是如果许多不同的地方使用monopoly.boardwalk
怎么办?现在,您必须确保所有这些位置在本地缓存值。 或你可以让Monopoly
类负责缓存。
cached_property
可以让类变得容易,而不是属性的使用者。
如果你正在努力寻找在许多不同地方使用的东西的例子:在一个体积适中的Django应用程序中你有模板,视图和后端代码都可能触及给定的模型。其中一些地方本身就是Django框架(比如管理界面),当你向模型中添加昂贵的操作时更新所有这些地方是不切实际的。使用装饰器是实用的;把责任放在模型中可以使所有其他代码更简单。