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

Reply via email to