#!/usr/bin/env python3

import functools


def add_to_cache(obj, name, val):
    """Add a result to the cache of an object."""
    if not hasattr(obj, "_memoize_cache"):
        obj._memoize_cache = dict()
    obj._memoize_cache[name] = val
    return obj


def get_from_cache(obj, name):
    """Get an item from the cache."""
    if not is_in_cache(obj, name):
        raise RuntimeError("Object does not have item {} stored in cache.".format(name))
    return obj._memoize_cache[name]


def is_in_cache(obj, name):
    return hasattr(obj, "_memoize_cache") and name in obj._memoize_cache


def cached(method=None, name=None):
    """A decorator allowing for specifying the name of a cache, allowing it to be modified elsewhere."""
    if method is None:
        return functools.partial(cached, name=name)

    @functools.wraps(method)
    def g(self, *args, **kwargs):
        cache_name = name if name is not None else method
        if not is_in_cache(self, cache_name):
            add_to_cache(self, cache_name, method(self, *args, **kwargs))
        return get_from_cache(self, cache_name)

    return g


def is_cached(self, name):
    """
    Determine if a cached item has been computed
    """
    return hasattr(self, "_memoize_cache") and name in self._memoize_cache.keys()

@@ -34,16 +34,30 @@
 nctools%0A
+import pickle%0A
 %0A%0Adef ad
@@ -81,16 +81,204 @@
 ame, val
+, *args, **kwargs):%0A    %22%22%22Add a result to the cache of an object.%22%22%22%0A    return _add_to_cache(obj, name, *args, pickle.dumps(kwargs))%0A%0A%0Adef _add_to_cache(obj, name, val, *args, kwargs_pkl
 ):%0A    %22
@@ -398,14 +398,10 @@
 e = 
-dict()
+%7B%7D
 %0A   
@@ -420,20 +420,40 @@
 e_cache%5B
+(
 name
+, args, kwargs_pkl)
 %5D = val%0A
@@ -473,16 +473,17 @@
 j%0A%0A%0Adef 
+_
 get_from
@@ -494,24 +494,43 @@
 he(obj, name
+, *args, kwargs_pkl
 ):%0A    %22%22%22Ge
@@ -561,32 +561,33 @@
 .%22%22%22%0A    if not 
+_
 is_in_cache(obj,
@@ -587,24 +587,54 @@
 he(obj, name
+, *args, kwargs_pkl=kwargs_pkl
 ):%0A        r
@@ -747,20 +747,40 @@
 che%5B
+(
 name
+, args, kwargs_pkl)
 %5D%0A%0A%0Adef 
 is_i
@@ -775,16 +775,17 @@
 %5D%0A%0A%0Adef 
+_
 is_in_ca
@@ -793,24 +793,43 @@
 he(obj, name
+, *args, kwargs_pkl
 ):%0A    retur
@@ -861,28 +861,48 @@
 cache%22) and 
+(
 name
+, args, kwargs_pkl)
  in obj._mem
@@ -1252,16 +1252,58 @@
  method%0A
+        kwargs_pkl = pickle.dumps(kwargs)%0A
         
@@ -1309,16 +1309,17 @@
  if not 
+_
 is_in_ca
@@ -1334,24 +1334,54 @@
 , cache_name
+, *args, kwargs_pkl=kwargs_pkl
 ):%0A         
@@ -1383,16 +1383,17 @@
         
+_
 add_to_c
@@ -1444,16 +1444,46 @@
 *kwargs)
+, *args, kwargs_pkl=kwargs_pkl
 )%0A      
@@ -1491,16 +1491,17 @@
  return 
+_
 get_from
@@ -1527,196 +1527,50 @@
 name
-)%0A%0A    return g%0A%0A%0Adef is_cached(self, name):%0A    %22%22%22%0A    Determine if a cached item has been computed%0A    %22%22%22%0A    return hasattr(self, %22_memoize_cache%22) and name in self._memoize_cache.keys()
+, *args, kwargs_pkl=kwargs_pkl)%0A%0A    return g
 %0A

Support args & kwargs for memoize