|
本帖最后由 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[key]
- 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[lru.key].obj)
- del self.m_dict[lru.key]
-
- node = self.__Node(key, obj, time.time(), self.GetSortKey())
- self.m_dict[key] = 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[key]
- 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[key]
- del self.m_dict[key]
- 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[lru.key]
-
- 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 "[GetData]Key=" + str(key)
-
- def SetData(self, key, obj):
- print "[SetData]Key=" + str(key) + ",obj=" + str(obj)
-
-
- objTaskLru = TaskLru(10)
- for i in range(0, 20):
- objTaskLru[i] = i
复制代码
输出为
[SetData]Key=0,obj=0
[SetData]Key=1,obj=1
[SetData]Key=2,obj=2
[SetData]Key=3,obj=3
[SetData]Key=4,obj=4
[SetData]Key=5,obj=5
[SetData]Key=6,obj=6
[SetData]Key=7,obj=7
[SetData]Key=8,obj=8
[SetData]Key=9,obj=9
此代码在python2.6下编译通过。 |
|