python - 知道是否已经访问了 python 缓存的属性而不实际访问它
问题描述
有很多方法装饰器的例子可以将方法转换为缓存的属性。但有时,我想检查缓存是否“活动”,这意味着该属性已被访问并且缓存已被填充。
例如,如果我使用rows
缓存将 sql 表存储在 a 中rows
,我想根据缓存计算我的表的长度,如果它已被填充,但如果没有,则通过单独的 sql 调用。如何在rows
不触发其访问的情况下检查是否已被访问?
这是一个很好的装饰器,取自 David Beazley 的“Python Cookbook”)我正在使用它来满足我的缓存属性需求。我已经对其进行了增强以启用我当前的 hack。
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
自身“耦合”...
解决方案
仅供参考,属性缓存是 Python 3.8 标准库的一部分,通过functools
https://docs.python.org/3/library/functools.html?highlight=s#functools.cached_property
使用这个装饰器,你可以__dict__
直接访问你的类的属性来检查值是否被缓存。
使用文档中的示例...
import statistics
from functools import cached_property
class DataSet:
def __init__(self, sequence_of_numbers):
self._data = sequence_of_numbers
@cached_property
def stdev(self):
return statistics.stdev(self._data)
@cached_property
def variance(self):
return statistics.variance(self._data)
然后去测试一下...
ds = DataSet(range(1, 20))
ds.stdev
5.627314338711377
ds.__dict__
{'_data': range(1, 20), 'stdev': 5.627314338711377}
ds.variance
31.666666666666668
ds.__dict__
{'_data': range(1, 20), 'stdev': 5.627314338711377, 'variance': 31.666666666666668}
推荐阅读
- java - org.springframework.beans.factory.UnsatisfiedDependencyException:创建带有名称的 bean 时出错。无法让我的 springboot 应用程序运行
- selenium - 如何使用 API/端点更新 VSTS/Microsoft 测试管理器中的测试结果
- dataframe - 有什么方法可以在 PySpark 中对数据框执行与 mapPartitions 到 rdd 相同的操作吗?
- ruby-on-rails - 在 Rails 中显示来自具有直通关系的模型的数据
- javascript - 是否有向后兼容的方式来更新库以使用 getter?
- syntax - '=' 预计在 var_y 附近
- vim - python 模块导入错误 - python-mode [VIM]
- angular - 将 `combineLatest` 与 Angular 材质表一起使用
- vba - For Loop VBA 通过放入数组来加速
- angular - 元数据版本不匹配在条形码扫描仪中发现版本 4,预期为 3