2012-12-30 100 views
0

我已經實現了一個memoize裝飾器,它允許緩存一個函數。緩存鍵包含函數參數。同樣,裝飾器緩存一個函數,但忽略參數。下面是代碼:裝飾重新使用另一個裝飾器的實現

class ApplicationCache (Memcached): 

make_key方法:UltraJSON迅速提供了一個字符串,它SHA512散列成脆六角消化:

def make_key (self, *args, **kwargs): 

     kwargs.update (dict (enumerate (args))) 
     string = ujson.encode (sorted (kwargs.items())) 
     hashed = hashlib.sha512 (string) 

     return hashed.hexdigest() 

memoize裝飾:因爲Python 2。 x吸吮wrt完全合格的函數名,我只是強迫用戶提供一個合理的name

def memoize (self, name, timeout=None): 
     assert name 

     def decorator (fn): 
      @functools.wraps (fn) 
      def decorated (*args, **kwargs): 

       key = self.make_key (name, *args, **kwargs) 
       cached = self.get (key) 

       if cached is None: 
        cached = fn (*args, **kwargs) 
        self.set (key, cached, timeout=timeout) 

       return cached 
      return decorated 
     return decorator 

cached裝飾:它是memoize幾乎逐字複製與單例外,make_key忽略的參數:

def cached (self, name, timeout=None): 
     assert name 

     def decorator (fn): 
      @functools.wraps (fn) 
      def decorated (*args, **kwargs): 

       key = self.make_key (name) ## no args! 
       cached = self.get (key) 

       if cached is None: 
        cached = fn (*args, **kwargs) 
        self.set (key, cached, timeout=timeout) 

       return cached 
      return decorated 
     return decorator 

現在,我的問題cached是,它尖叫重新因子:它應該使用memoize和想法將消除fn(使用functools.partial也許?),如:

def cached (self, name, timeout=None): 

     ## Reuse the more general `memoize` to cache a function, 
     ## but only based on its name (ignoring the arguments) 

實際上,我不知道如果我在這裏多事了DRY原則,如果重複使用,甚至有可能,因爲目前執行的cached忽略的參數同時建立唯一鍵(但在調用裝飾函數時明顯是而不是)。

回答

1

我擺脫name論證,並提供關鍵的功能參數:

def memoize(self, timeout=None, keyfunc=self.make_key): 
    ... 
    key = keyfunc(function.__name__, *args, **kwargs) 
    ... 

cache那麼只會變成:

def cache(self, timeout=None): 
    return self.memoize(timeout, keyfunc=lambda f, *args, **kwargs: f.__name__) 
+0

輝煌,與裝飾工作必須我睜不開眼這個明顯的解決方案。謝謝。 ; D的要點可在這裏:https://gist.github.com/4417820 – hsk81

+0

@ hsk81:順便說一句,你爲什麼使用JSON串參數?只需要執行'str()'可能會更好,因爲這樣會更快,並且可以用於不可序列化的對象。 – Blender

+0

謝謝你是對的,用'unicode'替換'JSON.encode'(使用會話ID'sid'而不是會話);更新的要點可在https://gist.github.com/4418107獲取。 – hsk81