[Python-Dev] PEP 289 - Generator Expressions

Tim Peters tim.one at comcast.net
Wed May 5 17:24:40 EDT 2004


[Jewett, Jim J]
> 	t1 = (1,2,3)
> 	t2 = ("a", "b", "c")
> 	t3 = ("first", "second", "third")
>
> 	(x,y,z for x in t1 for y in t2 for z in t3)
>
> Do What I Mean is the crossproduct, 27 elements long,
> which you get with a list comprehension.

Well, that expression by itself will result in a generator-iterator getting
created, with no actual results.  If you put it in a context that drives
generation, then it will deliver 27 results, and regardless of whether
early-binding, late-binding, or mostly-late binding is used (although the
latter two are sensitive to changes in the bindings for t2 and t3, if any
such occur between the time the genexp is created and the time the genexp is
driven).  For mostly-late binding, it's the same as this Python program
today (stuffing the genexp in a list() call to force it to do something):

"""
t1 = (1,2,3)
t2 = ("a", "b", "c")
t3 = ("first", "second", "third")

def __g(primary):
    for x in primary:
        for y in t2:
            for z in t3:
                yield x, y, z

print list(__g(t1))
"""

Try running that, and see what you get.

> This will happen if at least (all but one) generators
> are pre-evaluated.

There are no generators in your example, apart from the one created by the
genexp itself.  You may be confusing generators with iterable objects.

> It will also happen if at least (all but one) generators are 
> restarted after they raise StopIterator.
>
> Doing strictly what happens today gets only
> 
> 	(1,'a',"first"), (1,'a',"second"), (1,'a',"third")

No -- run the above.  You'll get the 27 you expect.

> because t3 has raised StopIteration by the time t1 or t2
> advance.

The innermost "for" loop swallows StopIteration each of the 9 times it
occurs, and the outer for loops never see it.  They keep going.  This is how
"for" loops always work (nothing is changing wrt that).





More information about the Python-Dev mailing list