2010-12-14 86 views
7

我身邊有6,00,000 entries in MongoDB採用以下格式:的Python:構建LRU緩存

feature:category:count 

其中

  • 功能可以是任何文字,
  • 類是正還是負,和
  • count表明該類別的文檔中發生了多少次特徵。

我想要緩存前1000個元組,讓我們說,以免每次查詢數據庫。

如何在Python中構建一個LRU緩存?或者有沒有已知的解決方案?

回答

3

Python 3.2 functools包括LRU cache。您可以輕鬆地從repo中挑選它,檢查是否必須調整它以適用於Python 2(不應該太難 - 可能使用itertools而不是某些內置函數 - 詢問您是否需要幫助)並完成。儘管如此,您需要將查詢包裝到可調用的對象中,並確保它依賴於(可哈希)函數參數。

+0

這看起來很有趣,但是如何從回購中獲得呢?我不知道該怎麼做\ – daydreamer 2010-12-15 18:36:01

+0

@learner:最簡單的方法是從我鏈接的文件中拷貝它。 – delnan 2010-12-15 18:40:30

+0

我試過,但是當我嘗試導入functools它拋出錯誤>>>進口functools 回溯(最近通話最後一個): 文件「」,1號線,在 文件「functools.py」,線路151 外地命中,未命中 ^ SyntaxError:無效的語法 sys.excepthook錯誤: – daydreamer 2010-12-15 19:06:17

5

除了Python 3.2中包含的版本外,Python核心開發人員Raymond Hettinger在Python Cookbook中還有一些LRU緩存配方,其中包括these

17

Python3.3中的LRU cache有O(1)插入,刪除和搜索。

該設計使用一個循環雙向鏈接的條目列表(排列成最舊到最新)和一個散列表來定位各個鏈接。緩存命中使用散列表來查找相關鏈接並將其移動到列表頭部。緩存未命中將刪除最舊的鏈接,並在鏈接列表的頭部創建一個新鏈接。

這是33行非常基本的Python(僅使用簡單的字典和列表操作)的簡化(但速度快)的版本。它運行在Python2.0和後(或PyPy或Jython或Python3.x):

class LRU_Cache: 

    def __init__(self, original_function, maxsize=1024): 
     # Link structure: [PREV, NEXT, KEY, VALUE] 
     self.root = [None, None, None, None] 
     self.root[0] = self.root[1] = self.root 
     self.original_function = original_function 
     self.maxsize = maxsize 
     self.mapping = {} 

    def __call__(self, *key): 
     mapping = self.mapping 
     root = self.root 
     link = mapping.get(key) 
     if link is not None: 
      link_prev, link_next, link_key, value = link 
      link_prev[1] = link_next 
      link_next[0] = link_prev 
      last = root[0] 
      last[1] = root[0] = link 
      link[0] = last 
      link[1] = root 
      return value 
     value = self.original_function(*key) 
     if len(mapping) >= self.maxsize: 
      oldest = root[1] 
      next_oldest = oldest[1] 
      root[1] = next_oldest 
      next_oldest[0] = root 
      del mapping[oldest[2]] 
     last = root[0] 
     last[1] = root[0] = mapping[key] = [last, root, key, value] 
     return value 


if __name__ == '__main__': 
    p = LRU_Cache(ord, maxsize=3) 
    for c in 'abcdecaeaa': 
     print(c, p(c)) 
1

另外還有backports中的蟒3.3版本lru_cache例如作爲this它運行在蟒2.7。如果您對兩層緩存感興趣(如果未在實例中緩存,它將檢查共享緩存),我已根據lru_cache的backport創建了lru2cache