Generator state/parameters

Michele Simionato michele.simionato at poste.it
Fri Dec 12 07:44:15 CET 2003


mertz at gnosis.cx (David Mertz, Ph.D.) wrote in message news:<mailman.85.1071171394.9307.python-list at python.org>...
> But the state need not be global, just a mutable object yielded by a
> generator.  As I thought about this fact, I have come to find Raymond
> Hettinger's proposals for enhancing simple generators less urgent (but I
> probably still vote +1, though now moot).
> 
>   >>> def echo():
>   ...     message = [None]
>   ...     while message[0] != "EXIT":
>   ...         yield message
>   ...
>   >>> for mess in echo():
>   ...     if mess[0] is not None: print mess[0]
>   ...     mess[0] = raw_input("Word: ")
>   ...
>   Word: foo
>   foo
>   Word: bar
>   bar
>   Word: EXIT
> 
> This is a toy example, but the point is that we are perfectly able to
> pass data back into a generator without using global state.

A more verbose but arguably more elegant way would be to wrap the
generator in a class. Let me repost some code I wrote some time ago.

"""An object-oriented interface to iterators-generators"""

class Iterator(object):
    """__gen__ is automatically called by __init__, so must have signature
    compatibile with __init__. Subclasses should not need to override __init__:
    you can do it, but you must do it cooperatively or, at least, ensure that
    __gen__ is called correctly and its value assigned to self.iterator. 
    """
    def __init__(self,*args,**kw):
        super(Iterator,self).__init__(*args,**kw)
        self.iterator=self.__gen__(*args,**kw)
    def __gen__(self,*args,**kw):
        "Trivial generator, to be overridden in subclasses"
        yield None
    def __iter__(self):
        return self
    def next(self):
        return self.iterator.next()

class MyIterator(Iterator):
    def __gen__(self):
        self.x=1
        yield self.x # will be changed outside the class
        yield self.x

iterator=MyIterator()

print iterator.next()
iterator.x=5
print iterator.next()

Wrapping the generator in the class, I can pass parameters to it (in
this case x). IOW, here the generator has an explicit "self" rather
than an implicit "__self__" as in the PEP. I am not sure if I like the 
PEP, wouldn't be easier to have a built-in iterator class?

   Michele




More information about the Python-list mailing list