title: Decorate re-using another decorator's implementation
body: <p>I've implemented a <code>memoize</code> decorator, which allows to cache a function. The cache key includes the function arguments. Similarly the <code>cached</code> decorator caches a function, but ignores the arguments. Here is the code:</p>
  
  <pre><code>class ApplicationCache (Memcached):
  </code></pre>
  
  <p>The <code>make_key</code> method: <em>UltraJSON</em> delivers quickly a string, which <em>SHA512</em> hashes into a crisp hex digest:</p>
  
  <pre><code>    def make_key (self, *args, **kwargs):
  
          kwargs.update (dict (enumerate (args)))
          string = ujson.encode (sorted (kwargs.items ()))
          hashed = hashlib.sha512 (string)
  
          return hashed.hexdigest ()
  </code></pre>
  
  <p>The <code>memoize</code> decorator: Since Python 2.x sucks w.r.t. fully qualified function names, I simply force the user to deliver a reasonable <code>name</code>:</p>
  
  <pre><code>    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
  </code></pre>
  
  <p>The <code>cached</code> decorator: It's almost a verbatim copy of <code>memoize</code> with the single exception where <code>make_key</code> ignores the arguments:</p>
  
  <pre><code>    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
  </code></pre>
  
  <p>Now, my problem with <code>cached</code> is, that it screams for re-factoring: It should use <code>memoize</code> and the idea would be to eliminate the arguments of <code>fn</code> (using <code>functools.partial</code> maybe?), like:</p>
  
  <pre><code>    def cached (self, name, timeout=None):
  
          ## Reuse the more general `memoize` to cache a function,
          ## but only based on its name (ignoring the arguments)
  </code></pre>
  
  <p>I'm actually not sure if I'm overdoing the DRY principle here, and if reuse is even possible, since the current implementation of <code>cached</code> ignores the arguments <em>only</em> while building the key (but obviously <em>not</em> while invoking the decorated function).</p>