class Result(object): pass class Failed(Result): pass failed = Failed() def cached(f, cacheCount=[0]): attr = "t" + str(cacheCount[0]); cacheCount[0] += 1 name = f.__name__ class CacheResult(Result): def __init__(self, i, rv): setattr(self, attr, (i, rv)) cache = {} def deco(self, i): key = i if key in cache and cache[key] is failed: raise ParseError() elif key in cache: return getattr(cache[key], attr) cache[key] = failed i, rv = f(self, i) cache[key] = CacheResult(i, rv) self.lastMatch.append((name, i)) return i, rv deco.__name__ = name return deco