Iteration and Generators¶
Iteration in Python¶
for
loops are very common in PythonThey operate on iterators
Just about any composite data type is iterable
Lists
Dictionaries
Strings
Files
…
What’s an Iterator?¶
An iterator is an object that yields a data stream …
The
next()
method yields the next element in the streamIf there is no next element, it raises the
StopIteration
exception
Question: where do iterators come from?
Answer: they are made by iterables
What’s an Iterable?¶
Iterables are objects that support iteration (Gosh!)
Iterables that are built into Python are for example …
Sequence, tuple
Dictionary (iteration yields key/value pairs)
Set
String
File
… and many more …
The Iterator Protocol (1)¶
Technically speaking …
- An iterable can make an iterator through the
__iter__()
method
- An iterable can make an iterator through the
Not usually done by hand
Done for me by
for
loop
for elem in iterable:
... do something with elem ...
The interpreter …
Creates an iterator before entering the loop (⟶
__iter__()
)Calls
next()
on that iterator before every iterationTerminates the loop when
StopIteration
is caught
The Iterator Protocol (2)¶
iterator = iter(iterable)
try:
i = next(iterator)
except StopIteration:
...
Often the calculation of the next element is complicated
⟶ object state has to be kept manually
Coding iterables is no fun
… at least not without language support
Generators: Motivation¶
Examples of complicated iteration …
Traverse a binary tree in depth-first or breadth-first order
Infinite sets like Fibonacci numbers
Stupid solution:
Store result in a list
Return the list
⟶ Problem with large iterables (Fibonacci?)
⟶ Best to generate on-demand
Generators: How?¶
def odd_numbers():
i = 0
while True:
if i%2 != 0:
yield i
i += 1
for j in odd_numbers():
print(j)
Observations¶
odd_numbers
is iterableyield
is magicEvery function that calls yield is a generator
Each call to
next(iterator)
(speak: execution of thefor
body) continues the function whereyield
left it.This is outright genius!
More on Generators¶
Python 2 to 3 transition
range()
is a generator in 3Python 2: returns a (temporary) list
… had to use
xrange()
to generateMany more places converted to generators
Standard library helpers
itertools
operator