| 
41
 | 
     1 #!/usr/bin/env python2
 | 
| 
 | 
     2 #
 | 
| 
 | 
     3 # Copyright 2011-2016 Google Inc.
 | 
| 
 | 
     4 #
 | 
| 
 | 
     5 # Licensed under the Apache License, Version 2.0 (the "License");
 | 
| 
 | 
     6 # you may not use this file except in compliance with the License.
 | 
| 
 | 
     7 # You may obtain a copy of the License at
 | 
| 
 | 
     8 #
 | 
| 
 | 
     9 #      http://www.apache.org/licenses/LICENSE-2.0
 | 
| 
 | 
    10 #
 | 
| 
 | 
    11 # Unless required by applicable law or agreed to in writing, software
 | 
| 
 | 
    12 # distributed under the License is distributed on an "AS IS" BASIS,
 | 
| 
 | 
    13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
| 
 | 
    14 # See the License for the specific language governing permissions and
 | 
| 
 | 
    15 # limitations under the License.
 | 
| 
 | 
    16 #
 | 
| 
 | 
    17 # vim: sw=2 sts=2 et
 | 
| 
 | 
    18 
 | 
| 
 | 
    19 class CachingFuncSequence(object):
 | 
| 
 | 
    20     def __init__(self, func, length, inc_func=None):
 | 
| 
 | 
    21         """
 | 
| 
 | 
    22         length: Length of this sequence.
 | 
| 
 | 
    23         func: function(index)
 | 
| 
 | 
    24         inc_func: function(index, value_of_previous)
 | 
| 
 | 
    25         """
 | 
| 
 | 
    26 
 | 
| 
 | 
    27         self.func = func
 | 
| 
 | 
    28         self.inc_func = inc_func
 | 
| 
 | 
    29         self.length = length
 | 
| 
 | 
    30         self._cache = {}
 | 
| 
 | 
    31 
 | 
| 
 | 
    32     def __getitem__(self, i):
 | 
| 
 | 
    33         if i < 0:
 | 
| 
 | 
    34             i += self.length
 | 
| 
 | 
    35         if i < 0 or i >= self.length:
 | 
| 
 | 
    36             raise IndexError()
 | 
| 
 | 
    37 
 | 
| 
 | 
    38         v = self._cache.get(i)
 | 
| 
 | 
    39         if v is not None:
 | 
| 
 | 
    40             return v
 | 
| 
 | 
    41 
 | 
| 
 | 
    42         if self.inc_func and i-1 in self._cache:
 | 
| 
 | 
    43             v = self.inc_func(i, self._cache[i-1])
 | 
| 
 | 
    44         else:
 | 
| 
 | 
    45             v = self.func(i)
 | 
| 
 | 
    46 
 | 
| 
 | 
    47         self._cache[i] = v
 | 
| 
 | 
    48         return v
 | 
| 
 | 
    49 
 | 
| 
 | 
    50     def __len__(self):
 | 
| 
 | 
    51         return self.length
 | 
| 
 | 
    52 
 | 
| 
 | 
    53     def __iter__(self):
 | 
| 
 | 
    54         for i in range(self.length):
 | 
| 
 | 
    55             yield self[i]
 |