question about generators

Andrew Koenig ark at research.att.com
Thu Aug 15 12:02:03 EDT 2002


Steve> But don't you think this is because of the fundamentally
Steve> different nature of "print" and "yield"?

At one level, of course I do -- but on another level, I don't.

A generator is a program that yields a sequence of values
to its caller.  If I have a program that prints a sequence
of values -- that is, a program that yields a sequence of
values to the printer -- one might think that by changing all
of the print statements to yield statements (ignoring formatting
issues, of course), one could change one program to another.

That is, suppose we have:

        def f():
                # ...
                print foo
                # ...

It is not all that absurd to suppose that we could transform the
program this way and maintain its behavior:

        def g():
                # ...
                yield foo
                # ...

        def f():
                for i in g():
                        print i

And indeed we can -- the only problem being recursive calls.

In other words, let's go back to my original example:

        def f():
           for <...>:
              if <condition>:
                 print <something>
              else:
                 <do something>
                 f()
                 <do something else>

and transform it exactly as I have done above:

        def g():
           for <...>:
              if <condition>:
                 yield <something>
              else:
                 <do something>
                 f()
                 <do something else>

        def f():
           for i in g():
              print i

This doesn't work because it's a ``shallow transformation'' that fails
in the face of recursive calls.  To find the corresponding deep
transformation, we have to map the recursion into an analogous recursion:


        def g():
           for <...>:
              if <condition>:
                 yield <something>
              else:
                 <do something>
                 for i in g()
                    yield i
                 <do something else>

and then it works.

-- 
Andrew Koenig, ark at research.att.com, http://www.research.att.com/info/ark



More information about the Python-list mailing list