| 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 14 matching lines...) Expand all Loading... |
| 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 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 # This class has a lower-case name because it is a decorator. | 35 class memoized(object): |
| 36 class memoized(object): # pylint: disable=invalid-name | |
| 37 | 36 |
| 38 def __init__(self, function): | 37 def __init__(self, function): |
| 39 self._function = function | 38 self._function = function |
| 40 self._results_cache = {} | 39 self._results_cache = {} |
| 41 | 40 |
| 42 def __call__(self, *args): | 41 def __call__(self, *args): |
| 43 try: | 42 try: |
| 44 return self._results_cache[args] | 43 return self._results_cache[args] |
| 45 except KeyError: | 44 except KeyError: |
| 46 result = self._function(*args) | 45 result = self._function(*args) |
| 47 self._results_cache[args] = result | 46 self._results_cache[args] = result |
| 48 return result | 47 return result |
| 49 except TypeError as e: | 48 except TypeError as e: |
| 50 raise TypeError( | 49 raise TypeError( |
| 51 'Cannot call memoized function %s with unhashable ' | 50 'Cannot call memoized function %s with unhashable ' |
| 52 'arguments: %s' % (self._function.__name__, e.message)) | 51 'arguments: %s' % (self._function.__name__, e.message)) |
| 53 | 52 |
| 54 # Use python "descriptor" protocol __get__ to appear | 53 # Use python "descriptor" protocol __get__ to appear |
| 55 # invisible during property access. | 54 # invisible during property access. |
| 56 def __get__(self, instance, owner): | 55 def __get__(self, instance, owner): |
| 57 # Return a function partial with object already bound as self. | 56 # Return a function partial with object already bound as self. |
| 58 return functools.partial(self.__call__, instance) | 57 return functools.partial(self.__call__, instance) |
| OLD | NEW |