我的问题是下面两段代码被解释器运行时是否相同:
class A(object):
def __init__(self):
self.__x = None
@property
def x(self):
if not self.__x:
self.__x = ... #some complicated action
return self.__x
还有更简单的
class A(object):
@property
def x(self):
return ... #some complicated action
也就是说,解释器是否足够智能,能够缓存属性x
?
我的假设是x
不会改变--找到它是 * 很难 * 的,但是一旦你找到了一次就没有理由再找到它了。
8条答案
按热度按时间ijnw1ujt1#
不,每次访问该属性时都将调用getter。
6bc51xsx2#
不,您需要添加一个memoize装饰器:
s3fp2yjn3#
对于任何可能在2020年阅读这篇文章的人来说,从Python 3.8开始,
functools
模块作为标准库的一部分提供了这个功能。https://docs.python.org/dev/library/functools.html#functools.cached_property
需要注意的是,定义自己的
__dict__
(或者根本不定义)或者使用__slots__
的类可能无法按预期工作。wmvff8tz4#
属性不会自动缓存它们的返回值。getter(和setter)用于在每次访问属性时调用。
然而,Denis Otkidach已经为此编写了一个很棒的缓存属性装饰器(发布在the Python Cookbook, 2nd edition中,最初也发布在ActiveState的PSF license下):
下面是一个演示其用法的示例:
4urapxun5#
Python 3.2提供了一个内置的装饰器,你可以用它来创建LRU缓存:
@functools.lru_cache(maxsize=128, typed=False)
或者,如果您使用的是Flask / Werkzeug,则有
@cached_property
装饰器。对于Django,尝试
from django.utils.functional import cached_property
mbzjlibv6#
因为我也有同样的问题,所以我不得不查了一下。
来自标准库的functools包也会得到一个cached_property装饰器,不幸的是,它只在Python 3.8中可用(截至本文发表时,它是Python 3.8a0),替代等待的方法是使用一个定制的装饰器,比如this one as mentioned by 0xc0de)或Django的装饰器,现在,然后再切换:
rwqw0loc7#
@unutbu的回答中提到的Denis Otkidach的decorator发表在O 'Reilly的Python Cookbook中,不幸的是,O' Reilly没有为代码示例指定任何许可证--就像重用代码的非正式许可一样。
如果你需要一个带有自由许可证的缓存属性装饰器,你可以使用Ken Seehof的
@cached_property
,它是在MIT license下显式发布的。k2arahey8#
注:为了可用选项的完整性而添加。
不,
property
默认不缓存。但是有几个选项可以实现这种行为,我想再添加一个:https://github.com/pydanny/cached-property