Python实现的一个简单LRU cache


Posted in Python onSeptember 26, 2014

起因:我的同事需要一个固定大小的cache,如果记录在cache中,直接从cache中读取,否则从数据库中读取。python的dict 是一个非常简单的cache,但是由于数据量很大,内存很可能增长的过大,因此需要限定记录数,并用LRU算法丢弃旧记录。key 是整型,value是10KB左右的python对象

分析:

1)可以想到,在对于cache,我们需要维护 key -> value 的关系

2)而为了实现LRU,我们又需要一个基于时间的优先级队列,来维护   timestamp  -> (key, value) 的关系

3)当cache 中的记录数达到一个上界maxsize时,需要将timestamp 最小的(key,value) 出队列

4) 当一个(key, value) 被命中时,实际上我们需要将它从队列中,移除并插入到队列的尾部。

从分析可以看出我们的cache 要达到性能最优需要满足上面的四项功能,对于队表的快速移除和插入,链表显然是最优的选择,为了快速移除,最好使用双向链表,为了插入尾部,需要有指向尾部的指针。

下面用python 来实现:

#encoding=utf-8
class LRUCache(object):

    def __init__(self, maxsize):

        # cache 的最大记录数

        self.maxsize = maxsize

        # 用于真实的存储数据

        self.inner_dd = {}

        # 链表-头指针

        self.head = None

        # 链表-尾指针 

        self.tail = None
    def set(self, key, value):

        # 达到指定大小      

        if len(self.inner_dd) >= self.maxsize:

            self.remove_head_node()
        node = Node()

        node.data = (key, value)

        self.insert_to_tail(node)

        self.inner_dd[key] = node
    def insert_to_tail(self, node):

        if self.tail is None:

            self.tail = node

            self.head = node

        else:

            self.tail.next = node

            node.pre = self.tail

            self.tail = node
    def remove_head_node(self):

        node = self.head

        del self.inner_dd[node.data[0]]

        node = None

        self.head = self.head.next

        self.head.pre = None

    def get(self, key):

        if key in self.inner_dd:

            # 如果命中, 需要将对应的节点移动到队列的尾部

            node = self.inner_dd.get(key)

            self.move_to_tail(node)

            return node.data[1]

        return None
    def move_to_tail(self, node):

        # 只需处理在队列头部和中间的情况

        if not (node == self.tail):

            if node == self.head:

                self.head = node.next

                self.head.pre = None

                self.tail.next = node

                node.pre = self.tail

                node.next = None

                self.tail = node

            else:

                pre_node = node.pre

                next_node = node.next

                pre_node.next = next_node

                next_node.pre = pre_node
                self.tail.next = node

                node.pre = self.tail

                node.next = None

                self.tail = node
class Node(object):

    def __init__(self):

        self.pre = None

        self.next = None

        # (key, value)

        self.data = None
    def __eq__(self, other):

        if self.data[0] == other.data[0]:

            return True

        return False

    def __str__(self):

       return str(self.data)
if __name__ == '__main__':

    cache = LRUCache(10)

    for i in xrange(1000):

        cache.set(i, i+1)

        cache.get(2)

    for key in cache.inner_dd:

        print key, cache.inner_dd[key]
Python 相关文章推荐
python 提取文件的小程序
Jul 29 Python
Python笔记(叁)继续学习
Oct 24 Python
Python实现从百度API获取天气的方法
Mar 11 Python
python中使用mysql数据库详细介绍
Mar 27 Python
神经网络理论基础及Python实现详解
Dec 15 Python
Python实现JSON反序列化类对象的示例
Jan 31 Python
Python文件如何引入?详解引入Python文件步骤
Dec 10 Python
使用Python的OpenCV模块识别滑动验证码的缺口(推荐)
May 10 Python
Python参数类型以及常见的坑详解
Jul 08 Python
python自动保存百度盘资源到百度盘中的实例代码
Aug 26 Python
Python3爬虫中pyspider的安装步骤
Jul 29 Python
python中的测试框架
Nov 13 Python
python网络编程实例简析
Sep 26 #Python
python的re模块应用实例
Sep 26 #Python
python实现自动登录人人网并访问最近来访者实例
Sep 26 #Python
编程语言Python的发展史
Sep 26 #Python
python人人网登录应用实例
Sep 26 #Python
python快速查找算法应用实例
Sep 26 #Python
python求众数问题实例
Sep 26 #Python
You might like
认识并使用PHP超级全局变量
2010/01/26 PHP
php简单统计字符串单词数量的方法
2015/06/19 PHP
PHP可变函数学习小结
2015/11/29 PHP
jquery中dom操作和事件的实例学习-表单验证
2011/11/30 Javascript
详谈jQuery操纵DOM元素属性 attr()和removeAtrr()方法
2015/01/22 Javascript
JavaScript 匿名函数和闭包介绍
2015/04/13 Javascript
js实现input框文字动态变换显示效果
2015/08/19 Javascript
jQuery实现可关闭固定于底(顶)部的工具条菜单效果
2015/11/06 Javascript
javascript实现unicode与ASCII相互转换的方法
2015/12/10 Javascript
jquery ztree实现树的搜索功能
2016/02/25 Javascript
简单模拟node.js中require的加载机制
2016/10/27 Javascript
详解微信小程序入门五: wxml文件引用、模版、生命周期
2017/01/20 Javascript
利用vue组件自定义v-model实现一个Tab组件方法示例
2017/12/06 Javascript
NodeJS 实现多语言的示例代码
2018/09/11 NodeJs
详解如何构建Promise队列实现异步函数顺序执行
2018/10/23 Javascript
解决VUE双向绑定失效的问题
2019/10/29 Javascript
VSCode 配置uni-app的方法
2020/07/11 Javascript
下载给定网页上图片的方法
2014/02/18 Python
Python标准库06之子进程 (subprocess包) 详解
2016/12/07 Python
Python实现的将文件每一列写入列表功能示例【测试可用】
2018/03/19 Python
Python爬取成语接龙类网站
2018/10/19 Python
python程序运行进程、使用时间、剩余时间显示功能的实现代码
2019/07/11 Python
python网络编程 使用UDP、TCP协议收发信息详解
2019/08/29 Python
Python英文文章词频统计(14份剑桥真题词频统计)
2019/10/13 Python
关于Numpy中的行向量和列向量详解
2019/11/30 Python
Pytorch之finetune使用详解
2020/01/18 Python
HTML5 拖拽批量上传文件的示例代码
2018/03/28 HTML / CSS
详解canvas绘制多张图的排列顺序问题
2019/01/21 HTML / CSS
美国在线健康和美容市场:Pharmapacks
2018/12/05 全球购物
迟到检讨书900字
2014/01/14 职场文书
大二法学专业职业生涯规划范文
2014/02/12 职场文书
温馨提示标语
2014/06/26 职场文书
2014年高数考试作弊检讨书
2014/12/14 职场文书
食品安全主题班会
2015/08/13 职场文书
MIME类型中application/xml与text/xml的区别介绍
2022/01/18 HTML / CSS
RestTemplate如何通过HTTP Basic Auth认证示例说明
2022/03/17 Java/Android