freeeyes 发表于 2011-2-16 14:23:46

一个Python写的支持LRU的类

本帖最后由 freeeyes 于 2011-2-16 14:30 编辑

最近工作需要,写了一个Python下的池,需要LRU支持,感觉写起来比C++的简单。
脚本语言在逻辑处理上,还是提供了很多方便的接口。
在这里记录一下
#!/usr/bin/env python
# -*- coding:utf-8 -*-#
'''
Created on 2011-2-16

@author: freeeyes
'''
import time
from heapq import heappush, heappop, heapify

class LRUCache(object):
    class __Node(object):
      def __init__(self, key, obj, timestamp, sort_key):
            object.__init__(self)
            self.key = key
            self.obj = obj
            self.atime = timestamp
            self.mtime = self.atime
            self._sort_key = sort_key
   
      def __cmp__(self, other):
            return cmp(self._sort_key, other._sort_key)
      
      def __repr__(self):
            return "<%s %s => %s (%s)>" % (self.__class__, self.key, self.obj, time.asctime(time.localtime(self.atime)))
      

    def __init__(self, nCacheCount):
      self.m_nCacheCount = nCacheCount
      self.m_heap   = []
      self.m_dict   = {}
      self.m_nCounter = 0

    def GetSortKey(self):
      self.m_nCounter += 1
      return self.m_nCounter
   
    def __len__(self):
      return len(self.m_heap)

    def __setitem__(self, key, obj):
      if self.m_dict.has_key(key):
            node = self.m_dict
            node.atime = time.time()
            node.mtime = node.atime
            node._sort_key = self.GetSortKey()
            heapify(self.m_heap)
      else:
            while len(self.m_heap) >= self.m_nCacheCount:
                lru = heappop(self.m_heap)
                self.SetData(lru.key, self.m_dict.obj)
                del self.m_dict
            
            node = self.__Node(key, obj, time.time(), self.GetSortKey())
            self.m_dict = node
            heappush(self.m_heap, node)

    def __getitem__(self, key):
      if not self.m_dict.has_key(key):
            return self.GetData(key)
      else:
            node = self.m_dict
            node.atime = time.time()
            node._sort_key = self.GetSortKey()
            heapify(self.m_heap)
            return node.obj

    def __delitem__(self, key):
      if not self.m_dict.has_key(key):
            return None
      else:
            node = self.m_dict
            del self.m_dict
            self.m_heap.remove(node)
            heapify(self.m_heap)
            return node.obj
      
    def __iter__(self):
      copy = self.m_heap[:]
      while len(copy) > 0:
            node = heappop(copy)
            yield node.key
      raise StopIteration
   
    def __setattr__(self, name, value):
      object.__setattr__(self, name, value)
      if name == 'size':
            while len(self.m_heap) > value:
                lru = heappop(self.m_heap)
                del self.m_dict

    def __repr__(self):
      return "<%s (%d elements)>" % (str(self.__class__), len(self.m_heap))
   
    def GetData(self, key):
      #重载实现函数,当找不到数据的时候,调用这个加载
      pass
   
    def SetData(self, key, obj):
      #当数据超过的池大小的时候,会调用这个。
      pass

这里因为我个人需要,我需要在GetItem()的时候,如果不在指定的字典里面,则提供外围一个接口,从别的介质获取数据(数据库中查找并加载进队列),如果队列达到上限,则剔除最不常用的那个对象,同时调用SetData()接口,让你把这个数据放在其他介质上(比如数据库)。
测试代码如下:(数据库部分省略,只是简单测试)
class TaskLru(LRUCache):
    def GetData(self, key):
      print "Key=" + str(key)
      
    def SetData(self, key, obj):
      print "Key=" + str(key) + ",obj=" + str(obj)
      
      
objTaskLru = TaskLru(10)
for i in range(0, 20):
    objTaskLru = i


输出为
Key=0,obj=0
Key=1,obj=1
Key=2,obj=2
Key=3,obj=3
Key=4,obj=4
Key=5,obj=5
Key=6,obj=6
Key=7,obj=7
Key=8,obj=8
Key=9,obj=9


此代码在python2.6下编译通过。
页: [1]
查看完整版本: 一个Python写的支持LRU的类