Have the function return both its desired result and a flag indicating whether the result should be cached, or have the wrapper pass the cache object to the function. (Or both!) Either way would work, but I like the first approach better. Maybe something like this...
import functools
def conditional_memoize(fn):
cache = {}
@functools.wraps(fn)
def wrapper(*args, **kwargs):
key = args + tuple(sorted(kwargs.iteritems()))
if key in cache:
return cache[key]
result, flag = fn(*args, **kwargs)
if flag:
cache[key] = result
return result
return wrapper