我将dict
子类化为具有易失性版本:在最后一次更新之后经过一段时间后,其值消失了(1):
import time
import collections
class Dict10min(dict):
def __init__(self):
super().__init__(self)
self.expire = 0 # when to expire
def __getitem__(self, item):
if time.time() < self.expire:
val = dict.__getitem__(self, item)
return val
else:
# purging the dict
self.clear()
raise KeyError("key {item} does not exist anymore".format(item=item))
def get(self, item, d=None):
if time.time() < self.expire:
try:
val = dict.__getitem__(self, item)
except KeyError:
return d
else:
return val
else:
# purging the dict
self.clear()
return None
def __setitem__(self, key, value):
# set expire time at 10 minutes from now
self.expire = time.time() + 5 # 5 seconds for tests, will be 600
dict.__setitem__(self, key, value)
# solution for update is from @johnrsharpe at http://stackoverflow.com/a/30242574/903011
def update(self, other=None, **kwargs):
if other is not None:
for k, v in other.items() if isinstance(other, collections.Mapping) else other:
self[k] = v
for k, v in kwargs.items():
self[k] = v
a = Dict10min()
a[1] = 2
time.sleep(6)
print(a.get(1))
a[3] = 4
print(a.get(1))
b = Dict10min()
b[1] = 2
time.sleep(6)
try:
print(b[1])
except KeyError:
print("entry does not exist anymore")
b[3] = 4
try:
print(b[1])
except KeyError:
print("entry does not exist anymore")
这正确输出
None
None
entry does not exist anymore
entry does not exist anymore
缺少的部分是处理整个Dict10min
对象的部分:当整体访问它时,不使用__getitem__
和.get()
,返回的是实际的字典的内容(而不是时间改变的版本)。
我应该在哪里挂钩以捕捉我的对象作为一个整体被访问的时刻(到return {}
)?
(1)代码在@TomDalton评论
之后更新答案 0 :(得分:1)
以下似乎对我有用。这是超级hacky!您需要为可能使用的任何其他“写入”方法添加挂钩。
import time
class ExpiringDict(dict):
def __init__(self, expiry_secs, *args, **kwargs):
self.expire = time.time() + expiry_secs
self.expiry_secs = expiry_secs
super(ExpiringDict, self).__init__(*args, **kwargs)
def _reset_expire(self):
self.expire = time.time() + self.expiry_secs
def _check_expire(self):
if time.time() > self.expire:
self.clear()
def __setitem__(self, key, value):
self._reset_expire()
return super(ExpiringDict, self).__setitem__(key, value)
def update(self, *args, **kwargs):
self._reset_expire()
return super(ExpiringDict, self).update(*args, **kwargs)
def __getitem__(self, *args, **kwargs):
self._check_expire()
return super(ExpiringDict, self).__getitem__(*args, **kwargs)
def __getattribute__(self, name):
attr = super(ExpiringDict, self).__getattribute__(name)
if name not in {"_check_expire", "expire", "clear"}:
self._check_expire()
return attr
它通过了与你上面相同的测试。遗憾的是,__getitem__
需要def __repr__(self, *args, **kwargs):
self._check_expire()
return dict.__repr__(self, *args, **kwargs)
:https://docs.python.org/3.5/reference/datamodel.html#special-lookup
因此,您可能需要添加其他方法。例如,如果你想像之前一样打印字典,你需要添加这样的repr:
$httpProvider
确保在打印前检查到期时间。