A quick cheatsheet showing Python's generators, covering usage of 'yield', behaviour on raising Exceptions, and Generator Expressions.
Basic yield
A generator function with two yields. Calling next
results in successive yields.
Once exhausted, it returns StopIteration
>>> def simple_gen():
... yield 1
... yield 2
...
>>> g = simple_gen()
>>> g
<generator object simple_gen at 0x1011c0bf0>
>>> next(g)
1
>>> next(g)
2
>>> next(g)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
Looping yield
An infinitely looping generator
>>> def looping_gen():
... i = 1
... while True:
... yield i
... i += 1
...
>>>
>>> g = looping_gen()
>>> next(g)
1
>>> next(g)
2
>>> next(g)
3
(and so on)
Closing a Generator
>>> g = looping_gen()
>>> g.close()
>>> g
<generator object looping_gen at 0x100f31000>
>>> next(g)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
Raising Exceptions
A generator that raises an Exception is immediately stopped.
>>> def throwing_gen():
... yield 1
... raise Exception
... yield 2
...
>>> g = throwing_gen()
>>> next(g)
1
>>> next(g)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in throwing_gen
Exception
>>> next(g)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
Iterating a Generator
>>> g = simple_gen()
>>> for x in g:
... print(x)
...
1
2
Or, convert to a list.
>>> g = simple_gen()
>>> list(g)
[1, 2]
Generator Expressions
List comprehensions are written with square brackets. Generator comprehensions are written with parentheses.
The difference; a generator is lazy list-comprehension.
>>> [x**2 for x in range(1,11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>> gen = (x**2 for x in range(1,11))
>>> gen
<generator object <genexpr> at 0x1036c2670>
>>> list(gen)
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
Chaining
>>> evens = (x for x in range(1,11) if x % 2 == 0)
>>> squared = (x**2 for x in evens)
>>> list(squared)
[4, 16, 36, 64, 100]
Further Reading (on Coroutines)
yield
can also be used to create coroutines. I don't often use them, but there's an excellent in-depth talk/course available here: http://www.dabeaz.com/coroutines/