码迷,mamicode.com
首页 > 系统相关 > 详细

lru_cache的增强实现

时间:2020-09-17 23:14:30      阅读:22      评论:0      收藏:0      [点我收藏+]

标签:调用   creat   duration   cond   size   pop   wrapper   pos   time   

  

from functools import wraps
import time,inspect,datetime

def m_cache(duration):
    def _cache(fn):
        local_cache={}
        @wraps(fn)
        def wrapper(*args,**kwargs):
            def clear_expire_keys(cache):
                expire_keys=[] # 记录过期key
                for k,(_,timestamp) in cache.items(): # 寻找过期key
                    if datetime.datetime.now().timestamp()-timestamp > duration:
                        expire_keys.append(k)
                for k in expire_keys: # 清除过期key
                    local_cache.pop(k)
            
            clear_expire_keys(local_cache)
            
            def make_key():
                key_dict={}
                sig=inspect.signature(fn)
                od=sig.parameters
                # param_list=[key for key in od.keys()]
                param_list=list(od.keys()) # inspect获取的参数列表
    
                # positional arguments
                for index,v in enumerate(args):
                    # print(index,v)
                    k=param_list[index]
                    key_dict[k]=v
    
                # keywords arguments
                for k,v in kwargs.items():
                    key_dict[k]=v
                # key_dict.update(kwargs)
                for k in od.keys(): # 对缺省参数的处理,置于key生成前
                    if k not in key_dict.keys():
                        key_dict[k]=od[k].default
    
                return tuple(sorted(key_dict.items()))
            key=make_key()
            
            print(key)
            
            if key not in local_cache.keys():
                ret=fn(*args,**kwargs)
                local_cache[key]=ret,datetime.datetime.now().timestamp()
            return local_cache[key][0]
        return wrapper
    return _cache

def logger(fn):
    @wraps(fn)
    def wrapper(*args,**kwargs):
        start=datetime.datetime.now()
        ret=fn(*args,**kwargs)
        delta=(datetime.datetime.now()-start).total_seconds()
        print(delta)
        return ret
    return wrapper

@logger
@m_cache(3)
def dix(x,y=6,z=3):
    time.sleep(z)
    print(x: {}\ty: {}.format(x,y))
    print(\n*3)
    return x+y
print(dix(7))
print(dix(7,y=6))
print(dix(x=7,y=6))
print(dix(y=6,x=7))
print(dix(4,8,y=6,x=7)) # 不符合原函数的定义,但是形成key一样,直接从local_cache取结果,避免了函数的的真正执行,故未报错

time.sleep(4)

print(dix(7))
print(dix(7,y=6))
print(dix(x=7,y=6))
print(dix(y=6,x=7))
print(dix(4,8,y=6,x=7))

 

缓存过期:

是dict中某个key过期,可以对每一个key单独设置过期时间,也可以对key设定统一过期时间

上面的装饰器增加一个参数,形成带参装饰器

@m_cache(3)代表key生存3s后过期

带参装饰器等于在原来的装饰器外面再嵌套一层

 

清除时机:

  1. 用到某个key之前,先判断是否过期,如果过期,重新调用函数生成新的key对应的value
  2. 一个线程负责清除过期key,本次在创建key之前,清除所有过期key

value的设计:

  1. key => (v,createtimestamp)
  2. key => (v,createtimestamp,duration) 
    duration是过期时间,这样每一个key就可以单独控制过期时间,这种设计中,-1可以表示永不过期,0可以表示立即过期

lru_cache的增强实现

标签:调用   creat   duration   cond   size   pop   wrapper   pos   time   

原文地址:https://www.cnblogs.com/dissipate/p/13657751.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有 京ICP备13008772号-2
迷上了代码!