Why don't generators execute until first yield?

Duncan Booth duncan.booth at invalid.invalid
Wed May 7 06:09:19 EDT 2008


Martin Sand Christensen <msc at es.aau.dk> wrote:

> Now to the main point. When a generator function is run, it 
immediately
> returns a generator, and it does not run any code inside the 
generator.
> Not until generator.next() is called is any code inside the generator
> executed, giving it traditional lazy evaluation semantics. Why don't
> generators follow the usual eager evaluation semantics of Python and
> immediately execute up until right before the first yield instead?

You mean you expect the semantics of generators to be that when you 
create them, or every time you call next() they run until they hit yield 
and then (except for the initial run) return the result that was yielded 
the time before? It is easy enough to implement that, but could be a bit 
confusing for the user.

>>> def greedy(fn):
    def greedygenerator(*args, **kw):
	def delayed():
		it = iter(fn(*args, **kw))
		try:
			res = it.next()
		except StopIteration:
			yield None
			return
		yield None
		for value in it:
			yield res
			res = value
		yield res
	it = delayed()
	it.next()
	return it
    return greedygenerator

>>> @greedy
def mygen(n):
	for i in range(n):
		print i
		yield i

		
>>> x = mygen(3)
0
>>> list(x)
1
2
[0, 1, 2]
>>> x = mygen(0)
>>> list(x)
[]
>>> 

Now try:

   for command in getCommandsFromUser():
       print "the result of that command was", execute(command)

where getCommandsFromUser is a greedy generator that reads from stdin, 
and see why generators don't work that way.




More information about the Python-list mailing list