Python实现LRUcache

介绍

设计一个简单通用的cache,具体思路:

  • 遵循lru算法,lru:近期最少使用算法
  • 使用python里的OrderDict来存储kv
  • cache 有大小限制和过期限制
  • 外部通过decorator方式来使用

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# cache.py
# coding: utf8
# LRUcache decorator
import time
from collections import OrderedDict


class Cache(object):
def init(self, expiration_time=10, cache_size=100):
self.cache = OrderedDict()
self.expiration_time = expiration_time
self.cache_size = cache_size

def call(self, func):
def _decorate(key):
if self.cache.has_key(key):
tm_point = self.cache[key].get(‘time’)
if time.time() - tm_point > self.expiration_time:
add_new = True # cache包含该key但是已经过期,需重新添加
else:
add_new = False # cache 包含该key且未过期,不需要重新添加
else:
add_new = True # cache没有该key,需要重新添加

if add_new:
value = func(key)
# 判断cache是否满,满了则从头部弹出一个
if len(self.cache) == self.cache_size:
self.cache.popitem(last=False)
else:
# 弹出使用现成的
value = self.cache.pop(key).get(‘value’)
cur = time.time()
# 添加一个新的或者更新旧的到尾部,并添加time
self.cache[key] = {‘time’: cur, ‘value’: value}

return value

return _decorate

测试一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# main.py
from cache import Cache as LRUcache

expiration_time=5
cache_size=10

@LRUcache(expiration_time, cache_size))
def get_auth(key):
print ‘get a new’
value = key
return value


def main():
for i in ‘a’ * 5:
print get_auth(i)


if name == main:
main()

输出

1
2
3
4
5
6
get a new
a
a
a
a
a

说明只是第一次去调用了get_auth,后面都是从cache取的。