Callbacks to generators

Peter Otten __peter__ at web.de
Tue Jun 8 02:43:35 EDT 2004


Dave Benjamin wrote:

> Is there a straightforward way to create a generator from a function that
> takes a callback? For instance, I have a function called "process":

Last time I asked there wasn't.

> The reason I am trying to do this is that I'd still like to be able to use
> "process" in code for Python 2.1, which does not support generators. I'd
> like to avoid implementing the entire thing twice or basing the callback
> version on the generator version.

When you know beforehand that your code should play nice with both the
visitor and the iterator pattern, you can use an iterator class instead of
a generator, e. g:

try:
    iter
except NameError:
    # prepare for the poor man's generator...
    class StopIteration(Exception):
        pass

    def iter(seq):
        try:
            seq.__iter__
        except AttributeError:
            pass
        else:
            return seq.__iter__()
        # test for as many special cases as you like, e. g.
        if isinstance(seq, type([])):
            return ListIterator(seq)
        raise TypeError

    hasGenerators = 0
else:
    hasGenerators = 1

# this is clumsy...
class ListIterator:
    """ Example of an iterator class """
    def __init__(self, seq):
        self.seq = seq
        self.index = 0

    def __iter__(self):
        return self

    def next(self):
        index = self.index
        self.index += 1
        try:
            return self.seq[index]
        except IndexError:
            raise StopIteration

def visit(seq, visitor):
    it = iter(seq)
    try:
        while 1:
            visitor(it.next())
    except StopIteration:
        pass

# ... but leaves client code unaffected:
if hasGenerators:
    print "using generator"
    for item in range(3):
        print 2 * item,
    print

def printItem(item):
    print 2 * item,

print "using visitor"
visit(range(3), printItem)
print

Peter





More information about the Python-list mailing list