diff options
author | Todd Gamblin <tgamblin@llnl.gov> | 2015-07-07 00:25:20 -0700 |
---|---|---|
committer | Todd Gamblin <tgamblin@llnl.gov> | 2015-08-16 12:50:39 -0700 |
commit | 92f398a897949e3b586abc38a934ae9d5cf1163c (patch) | |
tree | 8229c4b7df49ae4feb9d1aa94d6bd8981e243b05 | |
parent | da98b07624e2403807166e8a9d0dac3752f75c0f (diff) | |
download | spack-92f398a897949e3b586abc38a934ae9d5cf1163c.tar.gz spack-92f398a897949e3b586abc38a934ae9d5cf1163c.tar.bz2 spack-92f398a897949e3b586abc38a934ae9d5cf1163c.tar.xz spack-92f398a897949e3b586abc38a934ae9d5cf1163c.zip |
Better `@memoized` decorator.
-rw-r--r-- | lib/spack/llnl/util/lang.py | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/lib/spack/llnl/util/lang.py b/lib/spack/llnl/util/lang.py index 9e1bef18ca..be6dad867e 100644 --- a/lib/spack/llnl/util/lang.py +++ b/lib/spack/llnl/util/lang.py @@ -26,6 +26,7 @@ import os import re import sys import functools +import collections import inspect # Ignore emacs backups when listing modules @@ -170,16 +171,32 @@ def has_method(cls, name): return False -def memoized(obj): +class memoized(object): """Decorator that caches the results of a function, storing them in an attribute of that function.""" - cache = obj.cache = {} - @functools.wraps(obj) - def memoizer(*args, **kwargs): - if args not in cache: - cache[args] = obj(*args, **kwargs) - return cache[args] - return memoizer + def __init__(self, func): + self.func = func + self.cache = {} + + + def __call__(self, *args): + if not isinstance(args, collections.Hashable): + # Not hashable, so just call the function. + return self.func(*args) + + if args not in self.cache: + self.cache[args] = self.func(*args) + return self.cache[args] + + + def __get__(self, obj, objtype): + """Support instance methods.""" + return functools.partial(self.__call__, obj) + + + def clear(self): + """Expunge cache so that self.func will be called again.""" + self.cache.clear() def list_modules(directory, **kwargs): |