Source code for pySPACE.tools.memoize_generator

""" This module contains a class that provides memoization support for
generator. Most likely there would be cleaner and more general
ways of doing this but for the moment is suffices... 

Meaning of this method:
https://secure.wikimedia.org/wikipedia/en/wiki/Memoization

:Author: Jan Hendrik Metzen (jhm@informatik.uni-bremen.de)
:Created: 2008/11/25
"""

import itertools

[docs]class MemoizeGeneratorNotRefreshableException(Exception): pass
[docs]class MemoizeGenerator(object): """ Object to encapsulate a generator so that one iterate over the generators output several time. The output is computed only once and then stored in a cache. Be careful in cases where the generator might produce memory-intensive outputs! """
[docs] def __init__(self, generator, caching=False): """ Stores the generator and creates an empty cache .. note:: Since the output of the generator is ordered, the cache is an ordered sequence of variable length like a list """ self.generator = generator self.caching = caching self.refreshable = True if self.caching: self.cache = []
[docs] def _fetch_from_generator(self): """ Fetches one fresh value from the generator, store it in the cache and yield it """ while True: nextValue = self.generator.next() if self.caching: self.cache.append(nextValue) else: self.refreshable = False yield nextValue
[docs] def fresh(self): """ Return one generator that yields the same values like the internal one that was passed to __init__. .. note:: It does not recompute values that have already been requested before but just uses these from the internal cache. .. note:: Calling fresh invalidates all existing generators that have been created before using this method, i.e. there can only be one generator at a time """ if self.caching: return itertools.chain(self.cache, self._fetch_from_generator()) else: if not self.refreshable: raise MemoizeGeneratorNotRefreshableException( "This MemoizeGenerator does not cache elements from the generator and can thus not be reset") return self._fetch_from_generator()