缓存是一种将定量数据加以保存以备迎合后续请求的处理方式,旨在加快数据的检索速度。通过缓存机制将数据放到字典中,如果下次需要的时候可以直接到字典中获取。
class MyCache(object):
def __init__(self):
self.cache = {}
self.max_cache_size = 10
def __contains__(self, key):
"""
判断该键是否存在于缓存当中返回 True 或者 False
:param key:
:return:
"""
return key in self.cache
def update(self, key, value):
"""
更新该缓存字典 您可能选择性删除
:param key:
:param value:
:return:
"""
if key not in self.cache and len(self.cache) >= self.max_cache_size:
self.remove_oldest()
self.cache[key] = {'date_accessed': datetime.datetime.now(), "value": value}
def remove_oldest(self):
"""
删除备份最早访问日期的输入数据
:return:
"""
oldest_entry = None
# 根据其中的 date_accessed 字段找到最早的一个任务
for key in self.cache:
if oldest_entry is None:
oldest_entry = key
elif self.cache[key]["date_accessed"] < self.cache[oldest_entry]['date_accessed']:
oldest_entry = key
self.cache.pop(oldest_entry)
@property
def size(self):
"""
返回缓存的容量大小
:return:
"""
return len(self.cache)
if __name__ == "__main__":
# 测试缓存类
keys = ['test', 'red', 'fox', 'fence', 'junk', 'other', 'alpha', 'bravo', 'cal', 'devo', 'ele']
s = "abcdefghijklmnop"
cache = MyCache()
for i, key in enumerate(keys):
if key in cache:
continue
else:
value = ".".join([random.choice(s) for i in range(20)])
cache.update(key, value)
print(i+1, "------> ", cache.size)
在 python3.2 中 引入了一个非常优雅的缓存机器,即 functool 模块中的 lru_cache 装饰器
@functools.lru_cache(maxsize=None, typed=False)
使用functools模块的lur_cache装饰器,可以缓存最多 maxsize 个此函数的调用结果,从而提高程序执行的效率,
特别适合于耗时的函数。参数maxsize为最多缓存的次数,如果为None,则无限制,设置为2n时,性能最佳;
如果 typed=True(注意,在 functools32 中没有此参数),则不同参数类型的调用将分别缓存,例如 f(3) 和 f(3.0)。
被 lru_cache 装饰的函数会有 cache_clear 和 cache_info 两个方法,分别用于清除缓存和查看缓存信息。
这里用一个简单的示例演示 lru_cache 效果:
注: 有一个用 C 实现的,更快的,同时兼容 Python2 和 Python3 的第三方模块 fastcache 能够实现同样的功能。
from functools import lru_cache
@lru_cache(None)
def add(x, y):
print(f"calculating: {x} + {y}")
return x+y
print(add(1, 2))
print(add.cache_info()) # 显示缓存信息
add.cache_clear() # 清空缓存
# 在第二次执行的时候,并没有真正执行函数体, 二是直接返回缓存的结果
print(add(1, 2))
print(add(2, 3))
在web 程序中更常用的做法是实现一个自己的redis客户端封装,并且通过不同的前缀实现不同类别数据的缓存:
代码如下:
# 测试Python-redis的缓存功能
import json
import pprint
from redis import Redis
# from flask_restful import current_app
myredis = Redis.from_url("redis://localhost:6379/1", db=0)
class RedisCache(object):
def __init__(self, key_prefix="", encoder=None, decoder=None):
"""
初始化 redis 存储对象
:param key_prefix: 前缀
:param encoder: 编码
:param decoder: 解码
"""
self._key_prefix = key_prefix
# self._timeout = timeout
self.encoder = encoder
self.decoder = decoder
self._r = None
@property
def rds(self):
"""
获取一个底层的 redis 对象
:return:
"""
if self._r is not None:
return self._r
self._r = myredis
return self._r
# if getattr(current_app, "redis", None):
# self._r = current_app.redis
# else:
# rds = Redis.from_url(current_app.config["REDIS_URI"], db=0)
# current_app.redis = rds
# self._r = rds
# return self._r
def key(self, key):
"""
给 key 加上前缀
:param key:
:return:
"""
return f"{self._key_prefix}{key}"
def cache(self, key, value, timeout=None):
"""
存入
:param key:
:param value:
:param timeout:
:return:
"""
if self.encoder:
value = self.encoder(value)
# print(f"cache: {self.key(key)} {value}")
if timeout is not None:
self.rds.set(self.key(key), value, timeout)
else:
self.rds.set(self.key(key), value)
def get(self, key):
"""
取出
:param key:
:return:
"""
key = self.key(key)
value = self.rds.get(key)
if (value is not None) and self.decoder:
value = self.decoder(value)
return value
def delete(self, key):
"""
删除
:param key:
:return:
"""
self.rds.delete(self.key(key))
def get_keys(self, *keys):
"""
获取已存储键值
:param keys:
:return:
"""
pl = self.rds.pipeline()
for key in keys:
pl.get(self.key(key))
return pl.execute()
forked_infos = [
{"annualized_returns": None,
"create_time": 1562038393,
"desc": "失败的MACD策略",
"forked_id": "None",
"max_drawdown": "---",
"origin": None,
"parent": None
},
{"annualized_returns": None,
"create_time": 1562060612,
"desc": "失败的MACD策略",
"forked_id": "5d1b2744b264566d3f3f3632",
"max_drawdown": None,
"origin": "5d1ad079e86117f3883f361e",
"parent": "5d1ad079e86117f3883f361e"
}
]
mycache = RedisCache("DEMO", encoder=json.dumps, decoder=json.loads)
# Invalid input of type: 'list'. Convert to a byte, string or number first.
mycache.cache("5d1ad079e86117f3883f361e", forked_infos)
print(pprint.pformat(mycache.get("5d1ad079e86117f3883f361e")))
http://landcareweb.com/questions/35613/ru-he-zai-python-functools-lru-cacheshang-shi-yong-cache-clear
https://hugoren.iteye.com/blog/2378567