Python iterators and generators Iterators and generators Python

  • Slides: 19
Download presentation
Python iterators and generators

Python iterators and generators

Iterators and generators · Python makes good use of iterators · And has a

Iterators and generators · Python makes good use of iterators · And has a special kind of generator function that is powerful and useful · We’ll look at what both are · And why they are useful · See Norman Matloff’s excellent tutorial on python iterators and generators from which some of this material is borrowed

Files are iterators >>> f = open("myfile. txt") readlines() returns a list of the

Files are iterators >>> f = open("myfile. txt") readlines() returns a list of the lines in file >>> for l in f. readlines(): print len(l) 9 21 35 A file is a iterator, producing 43 new values as needed >>> f = open("myfile. txt") >>> for l in f: print len(l). . . 9 21 35 43

Files are iterators Iterators are supported wherever you can iterate over collections in containers

Files are iterators Iterators are supported wherever you can iterate over collections in containers (e. g. , lists, tuples, dictionaries) >>> f = open("myfile. txt") >>> map(len, f. readlines()) [9, 21, 35, 43] >>> f = open("myfile. txt") >>> map(len, f) [9, 21, 35, 43] >>>

Like sequences, but… · Iterators are like sequences (lists, tuples), but… · The entire

Like sequences, but… · Iterators are like sequences (lists, tuples), but… · The entire sequence is not materialized · Items produced one at a time as needed · The sequence can be infinite (e. g. , all positive integers) · You can create your own iterators if you write a function to generate the next item

next() Method · An iterator’s next method produces items >>> def intsfrom(i): while True:

next() Method · An iterator’s next method produces items >>> def intsfrom(i): while True: yield i i += 1 >>> ints = intsfrom(1) >>> ints. next() 1 >>> ints. next() 2 >>> ints. next() 3

Example: fib. py class fibnum: def __init__(self): self. fn 2 = 1 self. fn

Example: fib. py class fibnum: def __init__(self): self. fn 2 = 1 self. fn 1 = 1 next() used to generate successive values def next(self): # next() is the heart of any iterator # use of the following tuple to not only save lines of # code but insures that only the old values of self. fn 1 and # self. fn 2 are used in assigning the new values (self. fn 1, self. fn 2, oldfn 2) = (self. fn 1+self. fn 2, self. fn 1, self. fn 2) return oldfn 2 Classes with an __iter__() def __iter__(self): method are iterators return self http: //cs. umbc. edu/courses/331/fall 13/code/python/itgen/fib. py

Example: fib. py >>> from fib import * >>> f = fibnum() >>> for

Example: fib. py >>> from fib import * >>> f = fibnum() >>> for i in f: . . . print i. . . If i > 100: break 1 1 2 3 … 144 >>> http: //cs. umbc. edu/courses/331/fall 13/code/python/itgen/fib. py

Stopping an iterator class fibnum 20: def __init__(self): self. fn 2 = 1 #

Stopping an iterator class fibnum 20: def __init__(self): self. fn 2 = 1 # "f_{n-2}" self. fn 1 = 1 # "f_{n-1}" def next(self): (self. fn 1, self. fn 2, oldfn 2) = (self. fn 1+self. fn 2, self. fn 1, self. fn 2) if oldfn 2 > 20: raise Stop. Iteration return oldfn 2 def __iter__(self): return self Raise this error to tell consumer to stop http: //cs. umbc. edu/courses/331/fall 13/code/python/itgen/fib. py

Stopping an iterator >>> from fib import * >>> for i in fibnum 20():

Stopping an iterator >>> from fib import * >>> for i in fibnum 20(): print i 1 1 2 3 5 8 13 >>> http: //cs. umbc. edu/courses/331/fall 10/code/python/itgen/fib. py

More tricks · The list function materializes an iterator’s values as a list >>>

More tricks · The list function materializes an iterator’s values as a list >>> list(fibnum 20()) [1, 1, 2, 3, 5, 8, 13 · sum(), max(), min() know about iterators >>> sum(fibnum 20()) 33 >>> max(fibnum 20()) 13 >>> min(fibnum 20()) 1

itertools · The itertools library module has some useful tools for working with iterators

itertools · The itertools library module has some useful tools for working with iterators · islice() is like slice but works with streams produced by iterators >>> from itertools import * >>> list(islice(fibnum(), 6)) [1, 1, 2, 3, 5, 8] >>> list(islice(fibnum(), 6, 10)) [13, 21, 34, 55] · See also imap, ifilter, …

Python generators · Python generators generate iterators · They are more powerful and convenient

Python generators · Python generators generate iterators · They are more powerful and convenient · Write a regular function and instead of calling return to produce a value, call yield instead · When another value is needed, the generator function picks up where it left off · Raise the Stop. Iteration exception or call return when you are done

Generator example def gy(): x=2 y=3 yield x, y, x+y z = 12 yield

Generator example def gy(): x=2 y=3 yield x, y, x+y z = 12 yield z/x yield z/y return >>> from gen import * >>> g = gy() >>> g. next() (2, 3, 5) >>> g. next() 6 >>> g. next() 4 >>> g. next() Traceback (most recent call last): File "<stdin>", line 1, in <module> Stop. Iteration >>> http: //cs. umbc. edu/courses/331/fall 13/code/python/itgen/gen. py

Generator example: fib() def fib( ): fn 2 = 1 fn 1 = 1

Generator example: fib() def fib( ): fn 2 = 1 fn 1 = 1 while True: (fn 1, fn 2, oldfn 2) = (fn 1+fn 2, fn 1, fn 2) yield oldfn 2 http: //cs. umbc. edu/courses/331/fall 13/code/python/itgen/gen. py

Generator example: getword() def getword(file): for line in file: for word in line. split():

Generator example: getword() def getword(file): for line in file: for word in line. split(): yield word return http: //cs. umbc. edu/courses/331/fall 13/code/python/itgen/gen. py

Remembers stack, too def inorder(tree): if tree: for x in inorder(tree. left): yield x

Remembers stack, too def inorder(tree): if tree: for x in inorder(tree. left): yield x yield tree. dat for x in inorder(tree. right): yield x

Sieve of Eratosthenes def intsfrom(i): # generator for ints >= I while True: yield

Sieve of Eratosthenes def intsfrom(i): # generator for ints >= I while True: yield i i += 1 �� def nextn(g, n): # next n items in generator g return [g. next() for i in xrange(n)] def remove(n, g): # remove multiples of n for x in g: if x % n: yield x def sieve(ints): # generator for primes p = ints. next() yield p for p in sieve(remove(p, ints)): yield p def main(): primes = sieve(intsfrom(2)) while True: print "Next 10 primes" print nextn(primes, 10) raw_input('--more-- ') if __name__ == "__main__": main()

A session python> python sieve. py Next 10 primes [2, 3, 5, 7, 11,

A session python> python sieve. py Next 10 primes [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] --more-Next 10 primes [31, 37, 41, 43, 47, 53, 59, 61, 67, 71] --more-Next 10 primes [73, 79, 83, 89, 97, 101, 103, 107, 109, 113] --more-Next 10 primes [127, 131, 137, 139, 149, 151, 157, 163, 167, 173]