| OLD | NEW |
| 1 # Copyright (c) 2010 Google Inc. All rights reserved. | 1 # Copyright (c) 2010 Google Inc. All rights reserved. |
| 2 # | 2 # |
| 3 # Redistribution and use in source and binary forms, with or without | 3 # Redistribution and use in source and binary forms, with or without |
| 4 # modification, are permitted provided that the following conditions are | 4 # modification, are permitted provided that the following conditions are |
| 5 # met: | 5 # met: |
| 6 # | 6 # |
| 7 # * Redistributions of source code must retain the above copyright | 7 # * Redistributions of source code must retain the above copyright |
| 8 # notice, this list of conditions and the following disclaimer. | 8 # notice, this list of conditions and the following disclaimer. |
| 9 # * Redistributions in binary form must reproduce the above | 9 # * Redistributions in binary form must reproduce the above |
| 10 # copyright notice, this list of conditions and the following disclaimer | 10 # copyright notice, this list of conditions and the following disclaimer |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 28 | 28 |
| 29 # Python does not (yet) seem to provide automatic memoization. So we've | 29 # Python does not (yet) seem to provide automatic memoization. So we've |
| 30 # written a small decorator to do so. | 30 # written a small decorator to do so. |
| 31 | 31 |
| 32 import functools | 32 import functools |
| 33 | 33 |
| 34 | 34 |
| 35 class memoized(object): | 35 class memoized(object): |
| 36 |
| 36 def __init__(self, function): | 37 def __init__(self, function): |
| 37 self._function = function | 38 self._function = function |
| 38 self._results_cache = {} | 39 self._results_cache = {} |
| 39 | 40 |
| 40 def __call__(self, *args): | 41 def __call__(self, *args): |
| 41 try: | 42 try: |
| 42 return self._results_cache[args] | 43 return self._results_cache[args] |
| 43 except KeyError: | 44 except KeyError: |
| 44 # If we didn't find the args in our cache, call and save the results
. | 45 # If we didn't find the args in our cache, call and save the results
. |
| 45 result = self._function(*args) | 46 result = self._function(*args) |
| 46 self._results_cache[args] = result | 47 self._results_cache[args] = result |
| 47 return result | 48 return result |
| 48 # FIXME: We may need to handle TypeError here in the case | 49 # FIXME: We may need to handle TypeError here in the case |
| 49 # that "args" is not a valid dictionary key. | 50 # that "args" is not a valid dictionary key. |
| 50 | 51 |
| 51 # Use python "descriptor" protocol __get__ to appear | 52 # Use python "descriptor" protocol __get__ to appear |
| 52 # invisible during property access. | 53 # invisible during property access. |
| 53 def __get__(self, instance, owner): | 54 def __get__(self, instance, owner): |
| 54 # Return a function partial with obj already bound as self. | 55 # Return a function partial with obj already bound as self. |
| 55 return functools.partial(self.__call__, instance) | 56 return functools.partial(self.__call__, instance) |
| OLD | NEW |