I have set of values represented by a class. The class should be initialised with a generator to limit memory use.
The class itself is the iterable, having
__iter__, and the iterator, having
__next__ (see below).
Since I want to be able to iterate over the set of values multiple times, I cache the generated values in a list. In
__iter__, I check if I already have iterated over all values, and then return
iter of the cached values, or
self to continue with next, respectively.
Here's the code stripped down to the relevant parts:
class SetOfValues(object): def __init__(self, values): self._values = values self._values_generated =  self._done = False def __iter__(self): if self._done: return iter(self._values_generated) else: return self def __next__(self): try: value = next(self._values) self._values_generated.append(value) return value except StopIteration: self._done = True raise StopIteration("the end")
Then call it with:
x = SetOfValues((value for value in [1,2,3])) for i in x: print(i)
- Is this generally a good way to do it when you may need generated values more than once?
- Might it be better if
__iter__yields the value?
- In terms of usage of the class: might it be better to always rewind and let iter start with pos 0? Currently, iterating through the values, stopping early, then iterating again, would obviously just continue at the last index when not all values have been generated yet.