有许多方法装饰器的示例,它们将方法转换为缓存属性。但有时,我想检查缓存是否处于“活动”状态,这意味着该属性已被访问,缓存已被填充
例如,如果我使用rows
缓存在rows
中存储一个sql表,我希望根据缓存计算表的长度(如果已填充),如果未填充,则通过单独的sql调用。如何在不触发其访问的情况下检查rows
是否已被访问
这是一个很好的装饰器,取自David Beazley的“Python食谱”),我正在使用它满足缓存属性的需要。我已经对它进行了增强,以支持我当前的攻击
class lazyprop:
def __init__(self, func):
self.func = func
def __get__(self, instance, cls):
if instance is None:
return self
else:
value = self.func(instance)
setattr(instance, self.func.__name__, value)
setattr(instance, self.func.__name__ + '__cache_active', True) # my hack
return value
使用示例:
>>> class Test:
... def __init__(self, a):
... self.a = a
... @lazyprop
... def len(self):
... print('generating "len"')
... return len(self.a)
>>> t = Test([0, 1, 2])
>>> # See what happens if I ask if there is a 'len' attribute:
>>> hasattr(t, 'len')
generating "len"
3
>>> t.len
5
所以hasattr
实际上触发了len
方法调用,所以我不能使用它。无论如何,我不想使用它,因为我不是要求属性(键/引用)的存在,而是要求它的值的存在(即之前的计算)
根据标有“我的黑客”的行,我现在可以这样做:
def has_active_cache(instance, attr):
return getattr(instance, attr + '__cache_active', False)
>>> t = Test([0, 1, 2])
>>> print("Accessed:", has_active_cache(t, 'len'))
Accessed: False
>>> t.len
generating "len"
3
>>> print("Accessed:", has_active_cache(t, 'len'))
Accessed: True
但我相信还有比这更优雅的解决方案。也许一个会和lazyprop
本身“结合”在一起
仅供参考,通过
functools
,属性缓存是Python 3.8标准库的一部分https://docs.python.org/3/library/functools.html?highlight=s#functools.cached_property
使用这个装饰器,您可以直接访问类的
__dict__
属性来检查值是否被缓存使用文档中的示例
然后测试它
相关问题 更多 >
编程相关推荐