我有一个装饰器,它只是缓存返回值(在我的例子中称为@cached
),我希望将它与@property
结合使用。这通常很好。当我尝试使用expire
添加的@cached
属性时,我遇到了问题。
def cached(f):
cache = [None]
def inner(*args, **kwargs):
if cache[0]:
cache[0] = f(*args, **kwargs)
return cache[0]
def expire():
cache[0] = None
inner.expire = expire
return inner
class Example(object):
@property
@cached
def something_expensive(self):
print("expensive")
return "hello"
e = Example()
e.something_expensive
e.something_expensive.expire()
我如何才能访问过期功能?在被@property
替换后添加到函数中。我理解为什么这不起作用我对解决这个问题的方法很感兴趣。
一些限制:
@cached
装饰器@property
,因为我希望在单元测试中过期,它们使我的代码更好用。我认为一个相当糟糕的解决方案是(因为实际上我有很多属性,我想这样做):
class Example(object):
@cached
def _something_expensive(self):
return "hello"
@property
def something_expensive(self):
return self._something_expensive()
答案 0 :(得分:2)
您可以使用类字典访问它:
type(e).__dict__['something_expensive'].fget.expire()
一般来说,e.something_expensive
相当于:
type(e).__dict__['something_expensive'].__get__(e, type(e))
有关详细信息,请阅读:Descriptor HowTo Guide
请注意,在expiry
函数中,您没有将cache
从外部函数cached
函数设置为None
,您只需创建一个新的局部变量。你可能想做这样的事情:
def expire():
del cache[:]
cache.append(None)
在Python 3中,使用nonlocal
关键字更新cache
更加容易。