John O'Hagan wrote:
Inspired by some recent threads here about using classes to extend the
behaviour of iterators, I'm trying to replace some some top-level functions
aimed at doing such things with a class.
So far it's got a test for emptiness, a non-consuming peek-ahead method, and
an extended next() which can return slices as well as the normal mode, but
one thing I'm having a little trouble with is getting generator expressions
to restart when exhausted. This code works for generator functions:
class Regen(object):
"""Optionally restart generator functions"""
def __init__(self, generator, options=None, restart=False):
self.gen = generator
Your 'generator' parameter is actually a generator function -- a
function that created a generator when called.
self.options = options
Common practice would use 'args' instead of 'options'.
self.gen_call = generator(options)
If the callable takes multiple args, you want '*options' (or *args)
instead of 'options'.
That aside, your 'gen_call' parameter is actually a generator -- a
special type of iterator (uncallable object with __next__ (3.0) method).
It is worthwhile keeping the nomenclature straight. As you discovered,
generator expressions create generators, not generator functions. Other
than being given the default .__name__ attribute '<genexpr>', there is
otherwise nothing special about their result. So I would not try to
treat them specially. Initializing a Regen instance with *any*
generator (or other iterator) will fail.
On the other hand, your Regen instances could be initialized with *any*
callable that produces iterators, including iterator classes. So you
might as well call the parameters iter_func and iterator.
In general, for all iterators and not just generators, reiteration
requires a new iterator, either by duplicating the original or by saving
the values in a list and iterating through that.
Terry Jan Reedy
--
http://mail.python.org/mailman/listinfo/python-list