SlideShare a Scribd company logo
1 of 101
Download to read offline
TheVanishing Pattern
from
iterators to
generators in
Python Luciano Ramalho
ramalho@turing.com.br
@ramalhoorg
@ramalhoorg
Demo: laziness
in the Django Shell
2
>>> from django.db import connection
>>> q = connection.queries
>>> q
[]
>>> from municipios.models import *
>>> res = Municipio.objects.all()[:5]
>>> q
[]
>>> for m in res: print m.uf, m.nome
...
GO Abadia de Goiás
MG Abadia dos Dourados
GO Abadiânia
MG Abaeté
PA Abaetetuba
>>> q
[{'time': '0.000', 'sql': u'SELECT "municipios_municipio"."id",
"municipios_municipio"."uf", "municipios_municipio"."nome",
"municipios_municipio"."nome_ascii", "municipios_municipio"."meso_regiao_id",
"municipios_municipio"."capital", "municipios_municipio"."latitude",
"municipios_municipio"."longitude", "municipios_municipio"."geohash" FROM
"municipios_municipio" ORDER BY "municipios_municipio"."nome_ascii" ASC LIMIT 5'}]
>>> from django.db import connection
>>> q = connection.queries
>>> q
[]
>>> from municipios.models import *
>>> res = Municipio.objects.all()[:5]
>>> q
[]
>>> for m in res: print m.uf, m.nome
...
GO Abadia de Goiás
MG Abadia dos Dourados
GO Abadiânia
MG Abaeté
PA Abaetetuba
>>> q
[{'time': '0.000', 'sql': u'SELECT "municipios_municipio"."id",
"municipios_municipio"."uf", "municipios_municipio"."nome",
"municipios_municipio"."nome_ascii", "municipios_municipio"."meso_regiao_id",
"municipios_municipio"."capital", "municipios_municipio"."latitude",
"municipios_municipio"."longitude", "municipios_municipio"."geohash" FROM
"municipios_municipio" ORDER BY "municipios_municipio"."nome_ascii" ASC LIMIT 5'}]
this expression makes
a Django QuerySet
>>> from django.db import connection
>>> q = connection.queries
>>> q
[]
>>> from municipios.models import *
>>> res = Municipio.objects.all()[:5]
>>> q
[]
>>> for m in res: print m.uf, m.nome
...
GO Abadia de Goiás
MG Abadia dos Dourados
GO Abadiânia
MG Abaeté
PA Abaetetuba
>>> q
[{'time': '0.000', 'sql': u'SELECT "municipios_municipio"."id",
"municipios_municipio"."uf", "municipios_municipio"."nome",
"municipios_municipio"."nome_ascii", "municipios_municipio"."meso_regiao_id",
"municipios_municipio"."capital", "municipios_municipio"."latitude",
"municipios_municipio"."longitude", "municipios_municipio"."geohash" FROM
"municipios_municipio" ORDER BY "municipios_municipio"."nome_ascii" ASC LIMIT 5'}]
this expression makes
a Django QuerySet
QuerySets are “lazy”:
no database access
so far
>>> from django.db import connection
>>> q = connection.queries
>>> q
[]
>>> from municipios.models import *
>>> res = Municipio.objects.all()[:5]
>>> q
[]
>>> for m in res: print m.uf, m.nome
...
GO Abadia de Goiás
MG Abadia dos Dourados
GO Abadiânia
MG Abaeté
PA Abaetetuba
>>> q
[{'time': '0.000', 'sql': u'SELECT "municipios_municipio"."id",
"municipios_municipio"."uf", "municipios_municipio"."nome",
"municipios_municipio"."nome_ascii", "municipios_municipio"."meso_regiao_id",
"municipios_municipio"."capital", "municipios_municipio"."latitude",
"municipios_municipio"."longitude", "municipios_municipio"."geohash" FROM
"municipios_municipio" ORDER BY "municipios_municipio"."nome_ascii" ASC LIMIT 5'}]
this expression makes
a Django QuerySet
QuerySets are “lazy”:
no database access
so far
the query is made
only when we
iterate over the
results
@ramalhoorg
QuerySet is a lazy iterable
7
@ramalhoorg
QuerySet is a lazy iterable
technical term
8
@ramalhoorg
Lazy
• Avoids unnecessary work, by postponing it as long as possible
• The opposite of eager
9
In Computer Science, being
“lazy” is often a good thing!
@ramalhoorg
Now, back to basics...
10
@ramalhoorg
Iteration: C and Python
#include <stdio.h>
int main(int argc, char *argv[]) {
int i;
for(i = 0; i < argc; i++)
printf("%sn", argv[i]);
return 0;
}
import sys
for arg in sys.argv:
print arg
@ramalhoorg
Iteration: Java (classic)
class Arguments {
public static void main(String[] args) {
for (int i=0; i < args.length; i++)
System.out.println(args[i]);
}
}
$ java Arguments alfa bravo charlie
alfa
bravo
charlie
@ramalhoorg
Iteration: Java ≥1.5
$ java Arguments2 alfa bravo charlie
alfa
bravo
charlie
• Enhanced for (a.k.a. foreach)
since
2004
class Arguments2 {
public static void main(String[] args) {
for (String arg : args)
System.out.println(arg);
}
}
@ramalhoorg
Iteration: Java ≥1.5
• Enhanced for (a.k.a. foreach)
class Arguments2 {
public static void main(String[] args) {
for (String arg : args)
System.out.println(arg);
}
}
since
2004
import sys
for arg in sys.argv:
print arg
since
1991
@ramalhoorg
You can iterate over many
Python objects
• strings
• files
• XML: ElementTree nodes
• not limited to built-in types:
• Django QuerySet
• etc.
15
@ramalhoorg
So, what is an iterable?
• Informal, recursive definition:
• iterable: fit to be iterated
• just as:
edible: fit to be eaten
16
@ramalhoorg
The for loop statement is
not the only construct that
handles iterables...
17
List comprehension
● Compreensão de lista ou abrangência
● Exemplo: usar todos os elementos:
– L2 = [n*10 for n in L]
List comprehension
• An expression that builds a list from any iterable
>>> s = 'abracadabra'
>>> l = [ord(c) for c in s]
>>> l
[97, 98, 114, 97, 99, 97, 100, 97, 98, 114, 97]
input: any iterable object
output: a list (always)
@ramalhoorg
Set comprehension
• An expression that builds a set from any iterable
>>> s = 'abracadabra'
>>> set(s)
{'b', 'r', 'a', 'd', 'c'}
>>> {ord(c) for c in s}
{97, 98, 99, 100, 114}
19
@ramalhoorg
Dict comprehensions
• An expression that builds a dict from any iterable
>>> s = 'abracadabra'
>>> {c:ord(c) for c in s}
{'a': 97, 'r': 114, 'b': 98, 'c': 99, 'd': 100}
20
@ramalhoorg
Syntactic support for iterables
• Tuple unpacking,
parallel assignment
>>> a, b, c = 'XYZ'
>>> a
'X'
>>> b
'Y'
>>> c
'Z'
21
>>> l = [(c, ord(c)) for c in 'XYZ']
>>> l
[('X', 88), ('Y', 89), ('Z', 90)]
>>> for char, code in l:
... print char, '->', code
...
X -> 88
Y -> 89
Z -> 90
@ramalhoorg
Syntactic support for iterables (2)
• Function calls: exploding arguments with *
>>> import math
>>> def hypotenuse(a, b):
... return math.sqrt(a*a + b*b)
...
>>> hypotenuse(3, 4)
5.0
>>> sides = (3, 4)
>>> hypotenuse(sides)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: hypotenuse() takes exactly 2 arguments (1 given)
>>> hypotenuse(*sides)
5.0 22
@ramalhoorg
Built-in iterable types
• basestring
• str
• unicode
• dict
• file
• frozenset
• list
• set
• tuple
• xrange
23
@ramalhoorg
Built-in functions that take iterable
arguments
• all
• any
• filter
• iter
• len
• map
• max
• min
• reduce
• sorted
• sum
• zip
unrelated to compression
@ramalhoorg
Classic iterables in Python
25
@ramalhoorg
Iterator is...
• a classic design pattern
Design Patterns
Gamma, Helm, Johnson &Vlissides
Addison-Wesley,
ISBN 0-201-63361-2
26
@ramalhoorg
Head First Design
Patterns Poster
O'Reilly,
ISBN 0-596-10214-3
27
@ramalhoorg
Head First Design
Patterns Poster
O'Reilly,
ISBN 0-596-10214-3
28
“The Iterator Pattern
provides a way to access
the elements of an
aggregate object
sequentially without
exposing the underlying
representation.”
An iterable Train class
>>> train = Train(4)
>>> for car in train:
... print(car)
car #1
car #2
car #3
car #4
>>>
@ramalhoorg
class Train(object):
def __init__(self, cars):
self.cars = cars
def __len__(self):
return self.cars
def __iter__(self):
return TrainIterator(self)
class TrainIterator(object):
def __init__(self, train):
self.train = train
self.current = 0
def __next__(self): # Python 3
if self.current < len(self.train):
self.current += 1
return 'car #%s' % (self.current)
else:
raise StopIteration()
An iterable
Train with
iterator
iterable
iterator
@ramalhoorg
Iterable ABC
• collections.Iterable abstract base class
• A concrete subclass of Iterable must
implement .__iter__
• .__iter__ returns an Iterator
• You don’t usually call .__iter__ directly
• when needed, call iter(x)
31
@ramalhoorg
Iterator ABC
• Iterator provides
.next
or
.__next__
• .__next__ returns the next item
• You don’t usually call .__next__ directly
• when needed, call next(x)
Python 3
Python 2
Python ≥ 2.6
32
@ramalhoorg
for car in train:
• calls iter(train) to
obtain a TrainIterator
• makes repeated calls to
next(aTrainIterator)
until it raises StopIteration
class Train(object):
def __init__(self, cars):
self.cars = cars
def __len__(self):
return self.cars
def __iter__(self):
return TrainIterator(self)
class TrainIterator(object):
def __init__(self, train):
self.train = train
self.current = 0
def __next__(self): # Python 3
if self.current < len(self.train):
self.current += 1
return 'car #%s' % (self.current)
else:
raise StopIteration()
Train with
iterator
1
1
2
>>> train = Train(3)
>>> for car in train:
... print(car)
car #1
car #2
car #3
2
@ramalhoorg34 Richard Bartz/Wikipedia
@ramalhoorg
Iterable duck-like
creatures
35
@ramalhoorg
Design patterns in dynamic
languages
• Dynamic languages: Lisp, Smalltalk, Python,
Ruby, PHP, JavaScript...
• Many features not found in C++, where most
of the original 23 Design Patterns were
identified
• Java is more dynamic than C++, but much
more static than Lisp, Python etc.
36
Gamma, Helm, Johnson, Vlissides
a.k.a. the Gang of Four (GoF)
Peter Norvig:
“Design Patterns in Dynamic Languages”
@ramalhoorg
Dynamic types
• No need to declare types or interfaces
• It does not matter what an object claims do be, only what it is
capable of doing
38
@ramalhoorg
Duck typing
39
“In other words, don't
check whether it is-a duck:
check whether it quacks-
like-a duck, walks-like-a
duck, etc, etc, depending
on exactly what subset of
duck-like behaviour you
need to play your
language-games with.”
Alex Martelli
comp.lang.python (2000)
@ramalhoorg
A Python iterable is...
• An object from which the iter function can produce an iterator
• The iter(x) call:
• invokes x.__iter__() to obtain an iterator
• but, if x has no __iter__:
• iter makes an iterator which tries to fetch items from x by doing
x[0], x[1], x[2]...
sequence protocol
Iterable interface
40
@ramalhoorg
Train: a sequence of cars
train = Train(4)
41
train[0] train[1] train[2] train[3]
Train: a sequence of cars
>>> train = Train(4)
>>> len(train)
4
>>> train[0]
'car #1'
>>> train[3]
'car #4'
>>> train[-1]
'car #4'
>>> train[4]
Traceback (most recent call last):
...
IndexError: no car at 4
>>> for car in train:
... print(car)
car #1
car #2
car #3
car #4
Train: a sequence of cars
class Train(object):
def __init__(self, cars):
self.cars = cars
def __getitem__(self, key):
index = key if key >= 0 else self.cars + key
if 0 <= index < len(self): # index 2 -> car #3
return 'car #%s' % (index + 1)
else:
raise IndexError('no car at %s' % key)
if __getitem__ exists,
iteration “just works”
@ramalhoorg
The sequence protocol at work
>>> t = Train(4)
>>> len(t)
4
>>> t[0]
'car #1'
>>> t[3]
'car #4'
>>> t[-1]
'car #4'
>>> for car in t:
... print(car)
car #1
car #2
car #3
car #4
__len__
__getitem__
__getitem__
@ramalhoorg
Protocol
• protocol: a synonym for interface used in dynamic
languages like Smalltalk, Python, Ruby, Lisp...
• not declared, and not enforced by static checks
45
class Train(object):
def __init__(self, cars):
self.cars = cars
def __len__(self):
return self.cars
def __getitem__(self, key):
index = key if key >= 0 else self.cars + key
if 0 <= index < len(self): # index 2 -> car #3
return 'car #%s' % (index + 1)
else:
raise IndexError('no car at %s' % key)
Sequence protocol
__len__ and __getitem__
implement the immutable
sequence protocol
import collections
class Train(collections.Sequence):
def __init__(self, cars):
self.cars = cars
def __len__(self):
return self.cars
def __getitem__(self, key):
index = key if key >= 0 else self.cars + key
if 0 <= index < len(self): # index 2 -> car #3
return 'car #%s' % (index + 1)
else:
raise IndexError('no car at %s' % key)
Sequence ABC
• collections.Sequence abstract base class
abstract
methods
Python ≥ 2.6
import collections
class Train(collections.Sequence):
def __init__(self, cars):
self.cars = cars
def __len__(self):
return self.cars
def __getitem__(self, key):
index = key if key >= 0 else self.cars + key
if 0 <= index < len(self): # index 2 -> car #3
return 'car #%s' % (index + 1)
else:
raise IndexError('no car at %s' % key)
Sequence ABC
• collections.Sequence abstract base class
implement
these 2
import collections
class Train(collections.Sequence):
def __init__(self, cars):
self.cars = cars
def __len__(self):
return self.cars
def __getitem__(self, key):
index = key if key >= 0 else self.cars + key
if 0 <= index < len(self): # index 2 -> car #3
return 'car #%s' % (index + 1)
else:
raise IndexError('no car at %s' % key)
Sequence ABC
• collections.Sequence abstract base class
inherit these 5
@ramalhoorg
Sequence ABC
• collections.Sequence abstract base class
>>> train = Train(4)
>>> 'car #2' in train
True
>>> 'car #7' in train
False
>>> for car in reversed(train):
... print(car)
car #4
car #3
car #2
car #1
>>> train.index('car #3')
2 50
@ramalhoorg51 U.S. NRC/Wikipedia
@ramalhoorg
Generators
52
@ramalhoorg
Iteration in C (example 2)
#include <stdio.h>
int main(int argc, char *argv[]) {
int i;
for(i = 0; i < argc; i++)
printf("%d : %sn", i, argv[i]);
return 0;
}
$ ./args2 alfa bravo charlie
0 : ./args2
1 : alfa
2 : bravo
3 : charlie
@ramalhoorg
Iteration in Python (ex. 2)
import sys
for i in range(len(sys.argv)):
print i, ':', sys.argv[i]
$ python args2.py alfa bravo charlie
0 : args2.py
1 : alfa
2 : bravo
3 : charlie 54
not Pythonic
@ramalhoorg
Iteration in Python (ex. 2)
import sys
for i, arg in enumerate(sys.argv):
print i, ':', arg
$ python args2.py alfa bravo charlie
0 : args2.py
1 : alfa
2 : bravo
3 : charlie 55
Pythonic!
@ramalhoorg
import sys
for i, arg in enumerate(sys.argv):
print i, ':', arg
Iteration in Python (ex. 2)
$ python args2.py alfa bravo charlie
0 : args2.py
1 : alfa
2 : bravo
3 : charlie
this returns a lazy
iterable object
that object yields tuples
(index, item)
on demand, at each
iteration
56
@ramalhoorg
What
enumerate does >>> e = enumerate('Turing')
>>> e
<enumerate object at 0x...>
>>>
enumerate builds an
enumerate object
57
@ramalhoorg
What
enumerate does
isso constroi
um gerador
and that is iterable
>>> e = enumerate('Turing')
>>> e
<enumerate object at 0x...>
>>> for item in e:
... print item
...
(0, 'T')
(1, 'u')
(2, 'r')
(3, 'i')
(4, 'n')
(5, 'g')
>>>
58
enumerate builds an
enumerate object
@ramalhoorg
What
enumerate does
isso constroi
um gerador
the enumerate object
produces an
(index, item) tuple
for each next(e) call
>>> e = enumerate('Turing')
>>> e
<enumerate object at 0x...>
>>> next(e)
(0, 'T')
>>> next(e)
(1, 'u')
>>> next(e)
(2, 'r')
>>> next(e)
(3, 'i')
>>> next(e)
(4, 'n')
>>> next(e)
(5, 'g')
>>> next(e)
Traceback (most recent...):
...
StopIteration
• The enumerator object is an
example of a generator
@ramalhoorg
Iterator x generator
• By definition (in GoF) an iterator retrieves successive items
from an existing collection
• A generator implements the iterator interface (next) but
produces items not necessarily in a collection
• a generator may iterate over a collection, but return the items
decorated in some way, skip some items...
• it may also produce items independently of any existing data
source (eg. Fibonacci sequence generator)
60
Faraday disc
(Wikipedia)
@ramalhoorg
Very simple
generators
62
@ramalhoorg
Generator
function
• Any function that has the
yield keyword in its body
is a generator function
63
>>> def gen_123():
... yield 1
... yield 2
... yield 3
...
>>> for i in gen_123(): print(i)
1
2
3
>>>
the keyword gen was considered
for defining generator functions,
but def prevailed
@ramalhoorg
• When invoked, a
generator function
returns a
generator object
Generator
function
64
>>> def gen_123():
... yield 1
... yield 2
... yield 3
...
>>> for i in gen_123(): print(i)
1
2
3
>>> g = gen_123()
>>> g
<generator object gen_123 at ...>
@ramalhoorg
Generator
function
>>> def gen_123():
... yield 1
... yield 2
... yield 3
...
>>> g = gen_123()
>>> g
<generator object gen_123 at ...>
>>> next(g)
1
>>> next(g)
2
>>> next(g)
3
>>> next(g)
Traceback (most recent call last):
...
StopIteration
• Generator objects implement the
Iterator interface
65
@ramalhoorg
Generator
behavior
• Note how the output of
the generator function is
interleaved with the
output of the calling code
66
>>> def gen_AB():
... print('START')
... yield 'A'
... print('CONTINUE')
... yield 'B'
... print('END.')
...
>>> for c in gen_AB():
... print('--->', c)
...
START
---> A
CONTINUE
---> B
END.
>>>
@ramalhoorg
Generator
behavior
• The body is executed only
when next is called, and it
runs only up to the following
yield
>>> def gen_AB():
... print('START')
... yield 'A'
... print('CONTINUE')
... yield 'B'
... print('END.')
...
>>> g = gen_AB()
>>> next(g)
START
'A'
>>>
@ramalhoorg
Generator
behavior
• When the body of the function
returns, the generator object
throws StopIteration
• The for statement catches
that for you
68
>>> def gen_AB():
... print('START')
... yield 'A'
... print('CONTINUE')
... yield 'B'
... print('END.')
...
>>> g = gen_AB()
>>> next(g)
START
'A'
>>> next(g)
CONTINUE
'B'
>>> next(g)
END.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
for car in train:
• calls iter(train) to
obtain a generator
• makes repeated calls to next(generator) until
the function returns, which raises StopIteration
class Train(object):
def __init__(self, cars):
self.cars = cars
def __iter__(self):
for i in range(self.cars):
# index 2 is car #3
yield 'car #%s' % (i+1)
Train with
generator
function 1
1
2
>>> train = Train(3)
>>> for car in train:
... print(car)
car #1
car #2
car #3
2
Classic iterator
x generator
class Train(object):
def __init__(self, cars):
self.cars = cars
def __len__(self):
return self.cars
def __iter__(self):
return TrainIterator(self)
class TrainIterator(object):
def __init__(self, train):
self.train = train
self.current = 0
def __next__(self): # Python 3
if self.current < len(self.train):
self.current += 1
return 'car #%s' % (self.current)
else:
raise StopIteration()
class Train(object):
def __init__(self, cars):
self.cars = cars
def __iter__(self):
for i in range(self.cars):
yield 'car #%s' % (i+1)
2 classes,
12 lines of code
1 class,
3 lines of code
class Train(object):
def __init__(self, cars):
self.cars = cars
def __iter__(self):
for i in range(self.cars):
yield 'car #%s' % (i+1)
The pattern
just vanished
class Train(object):
def __init__(self, cars):
self.cars = cars
def __iter__(self):
for i in range(self.cars):
yield 'car #%s' % (i+1)
“When I see patterns in my
programs, I consider it a sign of
trouble. The shape of a program
should reflect only the problem it
needs to solve. Any other regularity
in the code is a sign, to me at least,
that I'm using abstractions that
aren't powerful enough -- often that
I'm generating by hand the
expansions of some macro that I
need to write.”
Paul Graham
Revenge of the nerds (2002)
Generator expression (genexp)
>>> g = (c for c in 'ABC')
>>> g
<generator object <genexpr> at 0x10045a410>
>>> for l in g:
... print(l)
...
A
B
C
>>>
@ramalhoorg
• When evaluated,
returns a generator object
>>> g = (n for n in [1, 2, 3])
>>> g
<generator object <genexpr> at 0x...>
>>> next(g)
1
>>> next(g)
2
>>> next(g)
3
>>> next(g)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
Generator expression (genexp)
for car in train:
• calls iter(train) to
obtain a generator
• makes repeated calls to next(generator) until
the function returns, which raises StopIteration
class Train(object):
def __init__(self, cars):
self.cars = cars
def __iter__(self):
for i in range(self.cars):
# index 2 is car #3
yield 'car #%s' % (i+1)
Train with
generator
function 1
1
2
>>> train = Train(3)
>>> for car in train:
... print(car)
car #1
car #2
car #3
2
for car in train:
• calls iter(train) to
obtain a generator
• makes repeated calls to next(generator) until
the function returns, which raises StopIteration
1
2
class Train(object):
def __init__(self, cars):
self.cars = cars
def __iter__(self):
return ('car #%s' % (i+1)
for i in range(self.cars))
Train with generator expression
>>> train = Train(3)
>>> for car in train:
... print(car)
car #1
car #2
car #3
class Train(object):
def __init__(self, cars):
self.cars = cars
def __iter__(self):
return ('car #%s' % (i+1) for i in range(self.cars))
Generator function
x genexpclass Train(object):
def __init__(self, cars):
self.cars = cars
def __iter__(self):
for i in range(self.cars):
yield 'car #%s' % (i+1)
@ramalhoorg
Built-in functions that return
iterables, iterators or generators
• dict
• enumerate
• frozenset
• list
• reversed
• set
• tuple
78
@ramalhoorg
• boundless generators
• count(), cycle(), repeat()
• generators which combine several iterables:
• chain(), tee(), izip(), imap(), product(), compress()...
• generators which select or group items:
• compress(), dropwhile(), groupby(), ifilter(), islice()...
• generators producing combinations of items:
• product(), permutations(), combinations()...
The itertools module Don’t reinvent the
wheel, use itertools!
this was not
reinvented:
ported from
Haskell
great for
MapReduce
@ramalhoorg
Generators in Python 3
• Several functions and methods of the standard library that used to
return lists, now return generators and other lazy iterables in Python 3
• dict.keys(), dict.items(), dict.values()...
• range(...)
• like xrange in Python 2.x (more than a generator)
• If you really need a list, just pass the generator to the list constructor.
Eg.: list(range(10))
80
@ramalhoorg
A practical example using
generator functions
• Generator functions to decouple reading and writing logic in a database
conversion tool designed to handle large datasets
https://github.com/ramalho/isis2json
81
@ramalhoorg
Main loop writes
JSON file
@ramalhoorg
Another loop reads
the input records
@ramalhoorg
One implementation:
same loop reads/writes
@ramalhoorg
But what if we need to read
another format?
@ramalhoorg
Functions in the
script
• iterMstRecords*
• iterIsoRecords*
• writeJsonArray
• main	

* generator functions
@ramalhoorg
main:
read command
line arguments
main: determine
input format
selected generator function is passed
as an argument
input generator function is selected
based on the input file extension
@ramalhoorg
writeJsonArray:
write JSON records
89
writeJsonArray:
iterates over one of the input
generator functions
selected generator function received as
an argument...
and called to produce input
generator
@ramalhoorg
iterIsoRecords:
read records
from ISO-2709
format file
generator function!
91
@ramalhoorg
iterIsoRecords
yields one record,
structured as a dict
creates a new dict in each
iteration
92
@ramalhoorg
iterMstRecords:
read records
from ISIS
.MST file
generator function!
iterIsoRecordsiterMstRecords
yields one record,
structured as a dict
creates a new dict in each
iteration
Generators at work
Generators at work
Generators at work
@ramalhoorg
We did not cover
• other generator methods:
• gen.close(): causes a GeneratorExit exception to be raised
within the generator body, at the point where it is paused
• gen.throw(e): causes any exception e to be raised within the
generator body, at the point it where is paused
Mostly useful for long-running processes.
Often not needed in batch processing scripts.
98
@ramalhoorg
We did not cover
• generator delegation with yield from
• sending data into a generator function with the
gen.send(x) method (instead of next(gen)),
and using yield as an expression to get the
data sent
• using generator functions as coroutines
not useful in the
context of iteration
Python ≥ 3.3
“Coroutines are not
related to iteration”
David Beazley
99
@ramalhoorg
How to learn generators
• Forget about .send() and coroutines: that is a completely different
subject. Look into that only after mastering and becoming really
confortable using generators for iteration.
• Study and use the itertools module
• Don’t worry about .close() and .throw() initially. You can be
productive with generators without using these methods.
• yield from is only available in Python 3.3, and only relevant if you
need to use .close() and .throw()
100
Q & A
Luciano Ramalho
luciano@ramalho.org
@ramalhoorg
https://github.com/ramalho/isis2json

More Related Content

What's hot

What We Talk About When We Talk About Unit Testing
What We Talk About When We Talk About Unit TestingWhat We Talk About When We Talk About Unit Testing
What We Talk About When We Talk About Unit TestingKevlin Henney
 
Advance features of C++
Advance features of C++Advance features of C++
Advance features of C++vidyamittal
 
Programming with GUTs
Programming with GUTsProgramming with GUTs
Programming with GUTsKevlin Henney
 
C aptitude scribd
C aptitude scribdC aptitude scribd
C aptitude scribdAmit Kapoor
 
Practical Class 12th (c++programs+sql queries and output)
Practical Class 12th (c++programs+sql queries and output) Practical Class 12th (c++programs+sql queries and output)
Practical Class 12th (c++programs+sql queries and output) Aman Deep
 
Advance C++notes
Advance C++notesAdvance C++notes
Advance C++notesRajiv Gupta
 
"Немного о функциональном программирование в JavaScript" Алексей Коваленко
"Немного о функциональном программирование в JavaScript" Алексей Коваленко"Немного о функциональном программирование в JavaScript" Алексей Коваленко
"Немного о функциональном программирование в JavaScript" Алексей КоваленкоFwdays
 
An Introduction to Property Based Testing
An Introduction to Property Based TestingAn Introduction to Property Based Testing
An Introduction to Property Based TestingC4Media
 
Programmation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScriptProgrammation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScriptLoïc Knuchel
 
Groovy grails types, operators, objects
Groovy grails types, operators, objectsGroovy grails types, operators, objects
Groovy grails types, operators, objectsHusain Dalal
 
Design Patterns - Compiler Case Study - Hands-on Examples
Design Patterns - Compiler Case Study - Hands-on ExamplesDesign Patterns - Compiler Case Study - Hands-on Examples
Design Patterns - Compiler Case Study - Hands-on ExamplesGanesh Samarthyam
 
Introducción a Elixir
Introducción a ElixirIntroducción a Elixir
Introducción a ElixirSvet Ivantchev
 

What's hot (20)

Functional C++
Functional C++Functional C++
Functional C++
 
Quality Python Homework Help
Quality Python Homework HelpQuality Python Homework Help
Quality Python Homework Help
 
What We Talk About When We Talk About Unit Testing
What We Talk About When We Talk About Unit TestingWhat We Talk About When We Talk About Unit Testing
What We Talk About When We Talk About Unit Testing
 
Advance features of C++
Advance features of C++Advance features of C++
Advance features of C++
 
Programming with GUTs
Programming with GUTsProgramming with GUTs
Programming with GUTs
 
Don't do this
Don't do thisDon't do this
Don't do this
 
C aptitude scribd
C aptitude scribdC aptitude scribd
C aptitude scribd
 
Practical Class 12th (c++programs+sql queries and output)
Practical Class 12th (c++programs+sql queries and output) Practical Class 12th (c++programs+sql queries and output)
Practical Class 12th (c++programs+sql queries and output)
 
Advance C++notes
Advance C++notesAdvance C++notes
Advance C++notes
 
"Немного о функциональном программирование в JavaScript" Алексей Коваленко
"Немного о функциональном программирование в JavaScript" Алексей Коваленко"Немного о функциональном программирование в JavaScript" Алексей Коваленко
"Немного о функциональном программирование в JavaScript" Алексей Коваленко
 
Slides
SlidesSlides
Slides
 
An Introduction to Property Based Testing
An Introduction to Property Based TestingAn Introduction to Property Based Testing
An Introduction to Property Based Testing
 
Programmation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScriptProgrammation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScript
 
Array notes
Array notesArray notes
Array notes
 
Groovy grails types, operators, objects
Groovy grails types, operators, objectsGroovy grails types, operators, objects
Groovy grails types, operators, objects
 
cluster(python)
cluster(python)cluster(python)
cluster(python)
 
Es6 overview
Es6 overviewEs6 overview
Es6 overview
 
Design Patterns - Compiler Case Study - Hands-on Examples
Design Patterns - Compiler Case Study - Hands-on ExamplesDesign Patterns - Compiler Case Study - Hands-on Examples
Design Patterns - Compiler Case Study - Hands-on Examples
 
C++ L01-Variables
C++ L01-VariablesC++ L01-Variables
C++ L01-Variables
 
Introducción a Elixir
Introducción a ElixirIntroducción a Elixir
Introducción a Elixir
 

Similar to The Vanishing Pattern: from iterators to generators in Python

An overview of Python 2.7
An overview of Python 2.7An overview of Python 2.7
An overview of Python 2.7decoupled
 
pa-pe-pi-po-pure Python Text Processing
pa-pe-pi-po-pure Python Text Processingpa-pe-pi-po-pure Python Text Processing
pa-pe-pi-po-pure Python Text ProcessingRodrigo Senra
 
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsMichael Pirnat
 
Beautiful python - PyLadies
Beautiful python - PyLadiesBeautiful python - PyLadies
Beautiful python - PyLadiesAlicia Pérez
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
 
Programming python quick intro for schools
Programming python quick intro for schoolsProgramming python quick intro for schools
Programming python quick intro for schoolsDan Bowen
 
Java Question-Bank-Class-8.pdf
Java Question-Bank-Class-8.pdfJava Question-Bank-Class-8.pdf
Java Question-Bank-Class-8.pdfAditya Kumar
 
Emerging Languages: A Tour of the Horizon
Emerging Languages: A Tour of the HorizonEmerging Languages: A Tour of the Horizon
Emerging Languages: A Tour of the HorizonAlex Payne
 
Python 표준 라이브러리
Python 표준 라이브러리Python 표준 라이브러리
Python 표준 라이브러리용 최
 
Introduction to Basic C programming 02
Introduction to Basic C programming 02Introduction to Basic C programming 02
Introduction to Basic C programming 02Wingston
 
C++ process new
C++ process newC++ process new
C++ process new敬倫 林
 
The Ring programming language version 1.5 book - Part 8 of 31
The Ring programming language version 1.5 book - Part 8 of 31The Ring programming language version 1.5 book - Part 8 of 31
The Ring programming language version 1.5 book - Part 8 of 31Mahmoud Samir Fayed
 
Advanced Web Technology ass.pdf
Advanced Web Technology ass.pdfAdvanced Web Technology ass.pdf
Advanced Web Technology ass.pdfsimenehanmut
 
Unit 5 Foc
Unit 5 FocUnit 5 Foc
Unit 5 FocJAYA
 
2 BytesC++ course_2014_c3_ function basics&parameters and overloading
2 BytesC++ course_2014_c3_ function basics&parameters and overloading2 BytesC++ course_2014_c3_ function basics&parameters and overloading
2 BytesC++ course_2014_c3_ function basics&parameters and overloadingkinan keshkeh
 
Python na Infraestrutura 
MySQL do Facebook

Python na Infraestrutura 
MySQL do Facebook
Python na Infraestrutura 
MySQL do Facebook

Python na Infraestrutura 
MySQL do Facebook
Artur Rodrigues
 
12th CBSE Practical File
12th CBSE Practical File12th CBSE Practical File
12th CBSE Practical FileAshwin Francis
 
Alexey Tsoy Meta Programming in C++ 16.11.17
Alexey Tsoy Meta Programming in C++ 16.11.17Alexey Tsoy Meta Programming in C++ 16.11.17
Alexey Tsoy Meta Programming in C++ 16.11.17LogeekNightUkraine
 
The Ring programming language version 1.7 book - Part 48 of 196
The Ring programming language version 1.7 book - Part 48 of 196The Ring programming language version 1.7 book - Part 48 of 196
The Ring programming language version 1.7 book - Part 48 of 196Mahmoud Samir Fayed
 

Similar to The Vanishing Pattern: from iterators to generators in Python (20)

An overview of Python 2.7
An overview of Python 2.7An overview of Python 2.7
An overview of Python 2.7
 
pa-pe-pi-po-pure Python Text Processing
pa-pe-pi-po-pure Python Text Processingpa-pe-pi-po-pure Python Text Processing
pa-pe-pi-po-pure Python Text Processing
 
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) Things
 
Beautiful python - PyLadies
Beautiful python - PyLadiesBeautiful python - PyLadies
Beautiful python - PyLadies
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
Programming python quick intro for schools
Programming python quick intro for schoolsProgramming python quick intro for schools
Programming python quick intro for schools
 
Python 1
Python 1Python 1
Python 1
 
Java Question-Bank-Class-8.pdf
Java Question-Bank-Class-8.pdfJava Question-Bank-Class-8.pdf
Java Question-Bank-Class-8.pdf
 
Emerging Languages: A Tour of the Horizon
Emerging Languages: A Tour of the HorizonEmerging Languages: A Tour of the Horizon
Emerging Languages: A Tour of the Horizon
 
Python 표준 라이브러리
Python 표준 라이브러리Python 표준 라이브러리
Python 표준 라이브러리
 
Introduction to Basic C programming 02
Introduction to Basic C programming 02Introduction to Basic C programming 02
Introduction to Basic C programming 02
 
C++ process new
C++ process newC++ process new
C++ process new
 
The Ring programming language version 1.5 book - Part 8 of 31
The Ring programming language version 1.5 book - Part 8 of 31The Ring programming language version 1.5 book - Part 8 of 31
The Ring programming language version 1.5 book - Part 8 of 31
 
Advanced Web Technology ass.pdf
Advanced Web Technology ass.pdfAdvanced Web Technology ass.pdf
Advanced Web Technology ass.pdf
 
Unit 5 Foc
Unit 5 FocUnit 5 Foc
Unit 5 Foc
 
2 BytesC++ course_2014_c3_ function basics&parameters and overloading
2 BytesC++ course_2014_c3_ function basics&parameters and overloading2 BytesC++ course_2014_c3_ function basics&parameters and overloading
2 BytesC++ course_2014_c3_ function basics&parameters and overloading
 
Python na Infraestrutura 
MySQL do Facebook

Python na Infraestrutura 
MySQL do Facebook
Python na Infraestrutura 
MySQL do Facebook

Python na Infraestrutura 
MySQL do Facebook

 
12th CBSE Practical File
12th CBSE Practical File12th CBSE Practical File
12th CBSE Practical File
 
Alexey Tsoy Meta Programming in C++ 16.11.17
Alexey Tsoy Meta Programming in C++ 16.11.17Alexey Tsoy Meta Programming in C++ 16.11.17
Alexey Tsoy Meta Programming in C++ 16.11.17
 
The Ring programming language version 1.7 book - Part 48 of 196
The Ring programming language version 1.7 book - Part 48 of 196The Ring programming language version 1.7 book - Part 48 of 196
The Ring programming language version 1.7 book - Part 48 of 196
 

More from OSCON Byrum

OSCON 2013 - Planning an OpenStack Cloud - Tom Fifield
OSCON 2013 - Planning an OpenStack Cloud - Tom FifieldOSCON 2013 - Planning an OpenStack Cloud - Tom Fifield
OSCON 2013 - Planning an OpenStack Cloud - Tom FifieldOSCON Byrum
 
Protecting Open Innovation with the Defensive Patent License
Protecting Open Innovation with the Defensive Patent LicenseProtecting Open Innovation with the Defensive Patent License
Protecting Open Innovation with the Defensive Patent LicenseOSCON Byrum
 
Using Cascalog to build an app with City of Palo Alto Open Data
Using Cascalog to build an app with City of Palo Alto Open DataUsing Cascalog to build an app with City of Palo Alto Open Data
Using Cascalog to build an app with City of Palo Alto Open DataOSCON Byrum
 
Finite State Machines - Why the fear?
Finite State Machines - Why the fear?Finite State Machines - Why the fear?
Finite State Machines - Why the fear?OSCON Byrum
 
Open Source Automotive Development
Open Source Automotive DevelopmentOpen Source Automotive Development
Open Source Automotive DevelopmentOSCON Byrum
 
How we built our community using Github - Uri Cohen
How we built our community using Github - Uri CohenHow we built our community using Github - Uri Cohen
How we built our community using Github - Uri CohenOSCON Byrum
 
Distributed Coordination with Python
Distributed Coordination with PythonDistributed Coordination with Python
Distributed Coordination with PythonOSCON Byrum
 
An overview of open source in East Asia (China, Japan, Korea)
An overview of open source in East Asia (China, Japan, Korea)An overview of open source in East Asia (China, Japan, Korea)
An overview of open source in East Asia (China, Japan, Korea)OSCON Byrum
 
Oscon 2013 Jesse Anderson
Oscon 2013 Jesse AndersonOscon 2013 Jesse Anderson
Oscon 2013 Jesse AndersonOSCON Byrum
 
US Patriot Act OSCON2012 David Mertz
US Patriot Act OSCON2012 David MertzUS Patriot Act OSCON2012 David Mertz
US Patriot Act OSCON2012 David MertzOSCON Byrum
 
OSCON 2012 US Patriot Act Implications for Cloud Computing - Diane Mueller, A...
OSCON 2012 US Patriot Act Implications for Cloud Computing - Diane Mueller, A...OSCON 2012 US Patriot Act Implications for Cloud Computing - Diane Mueller, A...
OSCON 2012 US Patriot Act Implications for Cloud Computing - Diane Mueller, A...OSCON Byrum
 
Big Data for each one of us
Big Data for each one of usBig Data for each one of us
Big Data for each one of usOSCON Byrum
 
BodyTrack: Open Source Tools for Health Empowerment through Self-Tracking
BodyTrack: Open Source Tools for Health Empowerment through Self-Tracking BodyTrack: Open Source Tools for Health Empowerment through Self-Tracking
BodyTrack: Open Source Tools for Health Empowerment through Self-Tracking OSCON Byrum
 
Declarative web data visualization using ClojureScript
Declarative web data visualization using ClojureScriptDeclarative web data visualization using ClojureScript
Declarative web data visualization using ClojureScriptOSCON Byrum
 
Using and Building Open Source in Google Corporate Engineering - Justin McWil...
Using and Building Open Source in Google Corporate Engineering - Justin McWil...Using and Building Open Source in Google Corporate Engineering - Justin McWil...
Using and Building Open Source in Google Corporate Engineering - Justin McWil...OSCON Byrum
 
A Look at the Network: Searching for Truth in Distributed Applications
A Look at the Network: Searching for Truth in Distributed ApplicationsA Look at the Network: Searching for Truth in Distributed Applications
A Look at the Network: Searching for Truth in Distributed ApplicationsOSCON Byrum
 
Life After Sharding: Monitoring and Management of a Complex Data Cloud
Life After Sharding: Monitoring and Management of a Complex Data CloudLife After Sharding: Monitoring and Management of a Complex Data Cloud
Life After Sharding: Monitoring and Management of a Complex Data CloudOSCON Byrum
 
Faster! Faster! Accelerate your business with blazing prototypes
Faster! Faster! Accelerate your business with blazing prototypesFaster! Faster! Accelerate your business with blazing prototypes
Faster! Faster! Accelerate your business with blazing prototypesOSCON Byrum
 
Comparing open source private cloud platforms
Comparing open source private cloud platformsComparing open source private cloud platforms
Comparing open source private cloud platformsOSCON Byrum
 
State of the Art Web Mapping with Open Source
State of the Art Web Mapping with Open SourceState of the Art Web Mapping with Open Source
State of the Art Web Mapping with Open SourceOSCON Byrum
 

More from OSCON Byrum (20)

OSCON 2013 - Planning an OpenStack Cloud - Tom Fifield
OSCON 2013 - Planning an OpenStack Cloud - Tom FifieldOSCON 2013 - Planning an OpenStack Cloud - Tom Fifield
OSCON 2013 - Planning an OpenStack Cloud - Tom Fifield
 
Protecting Open Innovation with the Defensive Patent License
Protecting Open Innovation with the Defensive Patent LicenseProtecting Open Innovation with the Defensive Patent License
Protecting Open Innovation with the Defensive Patent License
 
Using Cascalog to build an app with City of Palo Alto Open Data
Using Cascalog to build an app with City of Palo Alto Open DataUsing Cascalog to build an app with City of Palo Alto Open Data
Using Cascalog to build an app with City of Palo Alto Open Data
 
Finite State Machines - Why the fear?
Finite State Machines - Why the fear?Finite State Machines - Why the fear?
Finite State Machines - Why the fear?
 
Open Source Automotive Development
Open Source Automotive DevelopmentOpen Source Automotive Development
Open Source Automotive Development
 
How we built our community using Github - Uri Cohen
How we built our community using Github - Uri CohenHow we built our community using Github - Uri Cohen
How we built our community using Github - Uri Cohen
 
Distributed Coordination with Python
Distributed Coordination with PythonDistributed Coordination with Python
Distributed Coordination with Python
 
An overview of open source in East Asia (China, Japan, Korea)
An overview of open source in East Asia (China, Japan, Korea)An overview of open source in East Asia (China, Japan, Korea)
An overview of open source in East Asia (China, Japan, Korea)
 
Oscon 2013 Jesse Anderson
Oscon 2013 Jesse AndersonOscon 2013 Jesse Anderson
Oscon 2013 Jesse Anderson
 
US Patriot Act OSCON2012 David Mertz
US Patriot Act OSCON2012 David MertzUS Patriot Act OSCON2012 David Mertz
US Patriot Act OSCON2012 David Mertz
 
OSCON 2012 US Patriot Act Implications for Cloud Computing - Diane Mueller, A...
OSCON 2012 US Patriot Act Implications for Cloud Computing - Diane Mueller, A...OSCON 2012 US Patriot Act Implications for Cloud Computing - Diane Mueller, A...
OSCON 2012 US Patriot Act Implications for Cloud Computing - Diane Mueller, A...
 
Big Data for each one of us
Big Data for each one of usBig Data for each one of us
Big Data for each one of us
 
BodyTrack: Open Source Tools for Health Empowerment through Self-Tracking
BodyTrack: Open Source Tools for Health Empowerment through Self-Tracking BodyTrack: Open Source Tools for Health Empowerment through Self-Tracking
BodyTrack: Open Source Tools for Health Empowerment through Self-Tracking
 
Declarative web data visualization using ClojureScript
Declarative web data visualization using ClojureScriptDeclarative web data visualization using ClojureScript
Declarative web data visualization using ClojureScript
 
Using and Building Open Source in Google Corporate Engineering - Justin McWil...
Using and Building Open Source in Google Corporate Engineering - Justin McWil...Using and Building Open Source in Google Corporate Engineering - Justin McWil...
Using and Building Open Source in Google Corporate Engineering - Justin McWil...
 
A Look at the Network: Searching for Truth in Distributed Applications
A Look at the Network: Searching for Truth in Distributed ApplicationsA Look at the Network: Searching for Truth in Distributed Applications
A Look at the Network: Searching for Truth in Distributed Applications
 
Life After Sharding: Monitoring and Management of a Complex Data Cloud
Life After Sharding: Monitoring and Management of a Complex Data CloudLife After Sharding: Monitoring and Management of a Complex Data Cloud
Life After Sharding: Monitoring and Management of a Complex Data Cloud
 
Faster! Faster! Accelerate your business with blazing prototypes
Faster! Faster! Accelerate your business with blazing prototypesFaster! Faster! Accelerate your business with blazing prototypes
Faster! Faster! Accelerate your business with blazing prototypes
 
Comparing open source private cloud platforms
Comparing open source private cloud platformsComparing open source private cloud platforms
Comparing open source private cloud platforms
 
State of the Art Web Mapping with Open Source
State of the Art Web Mapping with Open SourceState of the Art Web Mapping with Open Source
State of the Art Web Mapping with Open Source
 

Recently uploaded

From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 

Recently uploaded (20)

From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 

The Vanishing Pattern: from iterators to generators in Python

  • 1. TheVanishing Pattern from iterators to generators in Python Luciano Ramalho ramalho@turing.com.br @ramalhoorg
  • 3. >>> from django.db import connection >>> q = connection.queries >>> q [] >>> from municipios.models import * >>> res = Municipio.objects.all()[:5] >>> q [] >>> for m in res: print m.uf, m.nome ... GO Abadia de Goiás MG Abadia dos Dourados GO Abadiânia MG Abaeté PA Abaetetuba >>> q [{'time': '0.000', 'sql': u'SELECT "municipios_municipio"."id", "municipios_municipio"."uf", "municipios_municipio"."nome", "municipios_municipio"."nome_ascii", "municipios_municipio"."meso_regiao_id", "municipios_municipio"."capital", "municipios_municipio"."latitude", "municipios_municipio"."longitude", "municipios_municipio"."geohash" FROM "municipios_municipio" ORDER BY "municipios_municipio"."nome_ascii" ASC LIMIT 5'}]
  • 4. >>> from django.db import connection >>> q = connection.queries >>> q [] >>> from municipios.models import * >>> res = Municipio.objects.all()[:5] >>> q [] >>> for m in res: print m.uf, m.nome ... GO Abadia de Goiás MG Abadia dos Dourados GO Abadiânia MG Abaeté PA Abaetetuba >>> q [{'time': '0.000', 'sql': u'SELECT "municipios_municipio"."id", "municipios_municipio"."uf", "municipios_municipio"."nome", "municipios_municipio"."nome_ascii", "municipios_municipio"."meso_regiao_id", "municipios_municipio"."capital", "municipios_municipio"."latitude", "municipios_municipio"."longitude", "municipios_municipio"."geohash" FROM "municipios_municipio" ORDER BY "municipios_municipio"."nome_ascii" ASC LIMIT 5'}] this expression makes a Django QuerySet
  • 5. >>> from django.db import connection >>> q = connection.queries >>> q [] >>> from municipios.models import * >>> res = Municipio.objects.all()[:5] >>> q [] >>> for m in res: print m.uf, m.nome ... GO Abadia de Goiás MG Abadia dos Dourados GO Abadiânia MG Abaeté PA Abaetetuba >>> q [{'time': '0.000', 'sql': u'SELECT "municipios_municipio"."id", "municipios_municipio"."uf", "municipios_municipio"."nome", "municipios_municipio"."nome_ascii", "municipios_municipio"."meso_regiao_id", "municipios_municipio"."capital", "municipios_municipio"."latitude", "municipios_municipio"."longitude", "municipios_municipio"."geohash" FROM "municipios_municipio" ORDER BY "municipios_municipio"."nome_ascii" ASC LIMIT 5'}] this expression makes a Django QuerySet QuerySets are “lazy”: no database access so far
  • 6. >>> from django.db import connection >>> q = connection.queries >>> q [] >>> from municipios.models import * >>> res = Municipio.objects.all()[:5] >>> q [] >>> for m in res: print m.uf, m.nome ... GO Abadia de Goiás MG Abadia dos Dourados GO Abadiânia MG Abaeté PA Abaetetuba >>> q [{'time': '0.000', 'sql': u'SELECT "municipios_municipio"."id", "municipios_municipio"."uf", "municipios_municipio"."nome", "municipios_municipio"."nome_ascii", "municipios_municipio"."meso_regiao_id", "municipios_municipio"."capital", "municipios_municipio"."latitude", "municipios_municipio"."longitude", "municipios_municipio"."geohash" FROM "municipios_municipio" ORDER BY "municipios_municipio"."nome_ascii" ASC LIMIT 5'}] this expression makes a Django QuerySet QuerySets are “lazy”: no database access so far the query is made only when we iterate over the results
  • 7. @ramalhoorg QuerySet is a lazy iterable 7
  • 8. @ramalhoorg QuerySet is a lazy iterable technical term 8
  • 9. @ramalhoorg Lazy • Avoids unnecessary work, by postponing it as long as possible • The opposite of eager 9 In Computer Science, being “lazy” is often a good thing!
  • 10. @ramalhoorg Now, back to basics... 10
  • 11. @ramalhoorg Iteration: C and Python #include <stdio.h> int main(int argc, char *argv[]) { int i; for(i = 0; i < argc; i++) printf("%sn", argv[i]); return 0; } import sys for arg in sys.argv: print arg
  • 12. @ramalhoorg Iteration: Java (classic) class Arguments { public static void main(String[] args) { for (int i=0; i < args.length; i++) System.out.println(args[i]); } } $ java Arguments alfa bravo charlie alfa bravo charlie
  • 13. @ramalhoorg Iteration: Java ≥1.5 $ java Arguments2 alfa bravo charlie alfa bravo charlie • Enhanced for (a.k.a. foreach) since 2004 class Arguments2 { public static void main(String[] args) { for (String arg : args) System.out.println(arg); } }
  • 14. @ramalhoorg Iteration: Java ≥1.5 • Enhanced for (a.k.a. foreach) class Arguments2 { public static void main(String[] args) { for (String arg : args) System.out.println(arg); } } since 2004 import sys for arg in sys.argv: print arg since 1991
  • 15. @ramalhoorg You can iterate over many Python objects • strings • files • XML: ElementTree nodes • not limited to built-in types: • Django QuerySet • etc. 15
  • 16. @ramalhoorg So, what is an iterable? • Informal, recursive definition: • iterable: fit to be iterated • just as: edible: fit to be eaten 16
  • 17. @ramalhoorg The for loop statement is not the only construct that handles iterables... 17
  • 18. List comprehension ● Compreensão de lista ou abrangência ● Exemplo: usar todos os elementos: – L2 = [n*10 for n in L] List comprehension • An expression that builds a list from any iterable >>> s = 'abracadabra' >>> l = [ord(c) for c in s] >>> l [97, 98, 114, 97, 99, 97, 100, 97, 98, 114, 97] input: any iterable object output: a list (always)
  • 19. @ramalhoorg Set comprehension • An expression that builds a set from any iterable >>> s = 'abracadabra' >>> set(s) {'b', 'r', 'a', 'd', 'c'} >>> {ord(c) for c in s} {97, 98, 99, 100, 114} 19
  • 20. @ramalhoorg Dict comprehensions • An expression that builds a dict from any iterable >>> s = 'abracadabra' >>> {c:ord(c) for c in s} {'a': 97, 'r': 114, 'b': 98, 'c': 99, 'd': 100} 20
  • 21. @ramalhoorg Syntactic support for iterables • Tuple unpacking, parallel assignment >>> a, b, c = 'XYZ' >>> a 'X' >>> b 'Y' >>> c 'Z' 21 >>> l = [(c, ord(c)) for c in 'XYZ'] >>> l [('X', 88), ('Y', 89), ('Z', 90)] >>> for char, code in l: ... print char, '->', code ... X -> 88 Y -> 89 Z -> 90
  • 22. @ramalhoorg Syntactic support for iterables (2) • Function calls: exploding arguments with * >>> import math >>> def hypotenuse(a, b): ... return math.sqrt(a*a + b*b) ... >>> hypotenuse(3, 4) 5.0 >>> sides = (3, 4) >>> hypotenuse(sides) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: hypotenuse() takes exactly 2 arguments (1 given) >>> hypotenuse(*sides) 5.0 22
  • 23. @ramalhoorg Built-in iterable types • basestring • str • unicode • dict • file • frozenset • list • set • tuple • xrange 23
  • 24. @ramalhoorg Built-in functions that take iterable arguments • all • any • filter • iter • len • map • max • min • reduce • sorted • sum • zip unrelated to compression
  • 26. @ramalhoorg Iterator is... • a classic design pattern Design Patterns Gamma, Helm, Johnson &Vlissides Addison-Wesley, ISBN 0-201-63361-2 26
  • 27. @ramalhoorg Head First Design Patterns Poster O'Reilly, ISBN 0-596-10214-3 27
  • 28. @ramalhoorg Head First Design Patterns Poster O'Reilly, ISBN 0-596-10214-3 28 “The Iterator Pattern provides a way to access the elements of an aggregate object sequentially without exposing the underlying representation.”
  • 29. An iterable Train class >>> train = Train(4) >>> for car in train: ... print(car) car #1 car #2 car #3 car #4 >>>
  • 30. @ramalhoorg class Train(object): def __init__(self, cars): self.cars = cars def __len__(self): return self.cars def __iter__(self): return TrainIterator(self) class TrainIterator(object): def __init__(self, train): self.train = train self.current = 0 def __next__(self): # Python 3 if self.current < len(self.train): self.current += 1 return 'car #%s' % (self.current) else: raise StopIteration() An iterable Train with iterator iterable iterator
  • 31. @ramalhoorg Iterable ABC • collections.Iterable abstract base class • A concrete subclass of Iterable must implement .__iter__ • .__iter__ returns an Iterator • You don’t usually call .__iter__ directly • when needed, call iter(x) 31
  • 32. @ramalhoorg Iterator ABC • Iterator provides .next or .__next__ • .__next__ returns the next item • You don’t usually call .__next__ directly • when needed, call next(x) Python 3 Python 2 Python ≥ 2.6 32
  • 33. @ramalhoorg for car in train: • calls iter(train) to obtain a TrainIterator • makes repeated calls to next(aTrainIterator) until it raises StopIteration class Train(object): def __init__(self, cars): self.cars = cars def __len__(self): return self.cars def __iter__(self): return TrainIterator(self) class TrainIterator(object): def __init__(self, train): self.train = train self.current = 0 def __next__(self): # Python 3 if self.current < len(self.train): self.current += 1 return 'car #%s' % (self.current) else: raise StopIteration() Train with iterator 1 1 2 >>> train = Train(3) >>> for car in train: ... print(car) car #1 car #2 car #3 2
  • 36. @ramalhoorg Design patterns in dynamic languages • Dynamic languages: Lisp, Smalltalk, Python, Ruby, PHP, JavaScript... • Many features not found in C++, where most of the original 23 Design Patterns were identified • Java is more dynamic than C++, but much more static than Lisp, Python etc. 36 Gamma, Helm, Johnson, Vlissides a.k.a. the Gang of Four (GoF)
  • 37. Peter Norvig: “Design Patterns in Dynamic Languages”
  • 38. @ramalhoorg Dynamic types • No need to declare types or interfaces • It does not matter what an object claims do be, only what it is capable of doing 38
  • 39. @ramalhoorg Duck typing 39 “In other words, don't check whether it is-a duck: check whether it quacks- like-a duck, walks-like-a duck, etc, etc, depending on exactly what subset of duck-like behaviour you need to play your language-games with.” Alex Martelli comp.lang.python (2000)
  • 40. @ramalhoorg A Python iterable is... • An object from which the iter function can produce an iterator • The iter(x) call: • invokes x.__iter__() to obtain an iterator • but, if x has no __iter__: • iter makes an iterator which tries to fetch items from x by doing x[0], x[1], x[2]... sequence protocol Iterable interface 40
  • 41. @ramalhoorg Train: a sequence of cars train = Train(4) 41 train[0] train[1] train[2] train[3]
  • 42. Train: a sequence of cars >>> train = Train(4) >>> len(train) 4 >>> train[0] 'car #1' >>> train[3] 'car #4' >>> train[-1] 'car #4' >>> train[4] Traceback (most recent call last): ... IndexError: no car at 4 >>> for car in train: ... print(car) car #1 car #2 car #3 car #4
  • 43. Train: a sequence of cars class Train(object): def __init__(self, cars): self.cars = cars def __getitem__(self, key): index = key if key >= 0 else self.cars + key if 0 <= index < len(self): # index 2 -> car #3 return 'car #%s' % (index + 1) else: raise IndexError('no car at %s' % key) if __getitem__ exists, iteration “just works”
  • 44. @ramalhoorg The sequence protocol at work >>> t = Train(4) >>> len(t) 4 >>> t[0] 'car #1' >>> t[3] 'car #4' >>> t[-1] 'car #4' >>> for car in t: ... print(car) car #1 car #2 car #3 car #4 __len__ __getitem__ __getitem__
  • 45. @ramalhoorg Protocol • protocol: a synonym for interface used in dynamic languages like Smalltalk, Python, Ruby, Lisp... • not declared, and not enforced by static checks 45
  • 46. class Train(object): def __init__(self, cars): self.cars = cars def __len__(self): return self.cars def __getitem__(self, key): index = key if key >= 0 else self.cars + key if 0 <= index < len(self): # index 2 -> car #3 return 'car #%s' % (index + 1) else: raise IndexError('no car at %s' % key) Sequence protocol __len__ and __getitem__ implement the immutable sequence protocol
  • 47. import collections class Train(collections.Sequence): def __init__(self, cars): self.cars = cars def __len__(self): return self.cars def __getitem__(self, key): index = key if key >= 0 else self.cars + key if 0 <= index < len(self): # index 2 -> car #3 return 'car #%s' % (index + 1) else: raise IndexError('no car at %s' % key) Sequence ABC • collections.Sequence abstract base class abstract methods Python ≥ 2.6
  • 48. import collections class Train(collections.Sequence): def __init__(self, cars): self.cars = cars def __len__(self): return self.cars def __getitem__(self, key): index = key if key >= 0 else self.cars + key if 0 <= index < len(self): # index 2 -> car #3 return 'car #%s' % (index + 1) else: raise IndexError('no car at %s' % key) Sequence ABC • collections.Sequence abstract base class implement these 2
  • 49. import collections class Train(collections.Sequence): def __init__(self, cars): self.cars = cars def __len__(self): return self.cars def __getitem__(self, key): index = key if key >= 0 else self.cars + key if 0 <= index < len(self): # index 2 -> car #3 return 'car #%s' % (index + 1) else: raise IndexError('no car at %s' % key) Sequence ABC • collections.Sequence abstract base class inherit these 5
  • 50. @ramalhoorg Sequence ABC • collections.Sequence abstract base class >>> train = Train(4) >>> 'car #2' in train True >>> 'car #7' in train False >>> for car in reversed(train): ... print(car) car #4 car #3 car #2 car #1 >>> train.index('car #3') 2 50
  • 53. @ramalhoorg Iteration in C (example 2) #include <stdio.h> int main(int argc, char *argv[]) { int i; for(i = 0; i < argc; i++) printf("%d : %sn", i, argv[i]); return 0; } $ ./args2 alfa bravo charlie 0 : ./args2 1 : alfa 2 : bravo 3 : charlie
  • 54. @ramalhoorg Iteration in Python (ex. 2) import sys for i in range(len(sys.argv)): print i, ':', sys.argv[i] $ python args2.py alfa bravo charlie 0 : args2.py 1 : alfa 2 : bravo 3 : charlie 54 not Pythonic
  • 55. @ramalhoorg Iteration in Python (ex. 2) import sys for i, arg in enumerate(sys.argv): print i, ':', arg $ python args2.py alfa bravo charlie 0 : args2.py 1 : alfa 2 : bravo 3 : charlie 55 Pythonic!
  • 56. @ramalhoorg import sys for i, arg in enumerate(sys.argv): print i, ':', arg Iteration in Python (ex. 2) $ python args2.py alfa bravo charlie 0 : args2.py 1 : alfa 2 : bravo 3 : charlie this returns a lazy iterable object that object yields tuples (index, item) on demand, at each iteration 56
  • 57. @ramalhoorg What enumerate does >>> e = enumerate('Turing') >>> e <enumerate object at 0x...> >>> enumerate builds an enumerate object 57
  • 58. @ramalhoorg What enumerate does isso constroi um gerador and that is iterable >>> e = enumerate('Turing') >>> e <enumerate object at 0x...> >>> for item in e: ... print item ... (0, 'T') (1, 'u') (2, 'r') (3, 'i') (4, 'n') (5, 'g') >>> 58 enumerate builds an enumerate object
  • 59. @ramalhoorg What enumerate does isso constroi um gerador the enumerate object produces an (index, item) tuple for each next(e) call >>> e = enumerate('Turing') >>> e <enumerate object at 0x...> >>> next(e) (0, 'T') >>> next(e) (1, 'u') >>> next(e) (2, 'r') >>> next(e) (3, 'i') >>> next(e) (4, 'n') >>> next(e) (5, 'g') >>> next(e) Traceback (most recent...): ... StopIteration • The enumerator object is an example of a generator
  • 60. @ramalhoorg Iterator x generator • By definition (in GoF) an iterator retrieves successive items from an existing collection • A generator implements the iterator interface (next) but produces items not necessarily in a collection • a generator may iterate over a collection, but return the items decorated in some way, skip some items... • it may also produce items independently of any existing data source (eg. Fibonacci sequence generator) 60
  • 63. @ramalhoorg Generator function • Any function that has the yield keyword in its body is a generator function 63 >>> def gen_123(): ... yield 1 ... yield 2 ... yield 3 ... >>> for i in gen_123(): print(i) 1 2 3 >>> the keyword gen was considered for defining generator functions, but def prevailed
  • 64. @ramalhoorg • When invoked, a generator function returns a generator object Generator function 64 >>> def gen_123(): ... yield 1 ... yield 2 ... yield 3 ... >>> for i in gen_123(): print(i) 1 2 3 >>> g = gen_123() >>> g <generator object gen_123 at ...>
  • 65. @ramalhoorg Generator function >>> def gen_123(): ... yield 1 ... yield 2 ... yield 3 ... >>> g = gen_123() >>> g <generator object gen_123 at ...> >>> next(g) 1 >>> next(g) 2 >>> next(g) 3 >>> next(g) Traceback (most recent call last): ... StopIteration • Generator objects implement the Iterator interface 65
  • 66. @ramalhoorg Generator behavior • Note how the output of the generator function is interleaved with the output of the calling code 66 >>> def gen_AB(): ... print('START') ... yield 'A' ... print('CONTINUE') ... yield 'B' ... print('END.') ... >>> for c in gen_AB(): ... print('--->', c) ... START ---> A CONTINUE ---> B END. >>>
  • 67. @ramalhoorg Generator behavior • The body is executed only when next is called, and it runs only up to the following yield >>> def gen_AB(): ... print('START') ... yield 'A' ... print('CONTINUE') ... yield 'B' ... print('END.') ... >>> g = gen_AB() >>> next(g) START 'A' >>>
  • 68. @ramalhoorg Generator behavior • When the body of the function returns, the generator object throws StopIteration • The for statement catches that for you 68 >>> def gen_AB(): ... print('START') ... yield 'A' ... print('CONTINUE') ... yield 'B' ... print('END.') ... >>> g = gen_AB() >>> next(g) START 'A' >>> next(g) CONTINUE 'B' >>> next(g) END. Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
  • 69. for car in train: • calls iter(train) to obtain a generator • makes repeated calls to next(generator) until the function returns, which raises StopIteration class Train(object): def __init__(self, cars): self.cars = cars def __iter__(self): for i in range(self.cars): # index 2 is car #3 yield 'car #%s' % (i+1) Train with generator function 1 1 2 >>> train = Train(3) >>> for car in train: ... print(car) car #1 car #2 car #3 2
  • 70. Classic iterator x generator class Train(object): def __init__(self, cars): self.cars = cars def __len__(self): return self.cars def __iter__(self): return TrainIterator(self) class TrainIterator(object): def __init__(self, train): self.train = train self.current = 0 def __next__(self): # Python 3 if self.current < len(self.train): self.current += 1 return 'car #%s' % (self.current) else: raise StopIteration() class Train(object): def __init__(self, cars): self.cars = cars def __iter__(self): for i in range(self.cars): yield 'car #%s' % (i+1) 2 classes, 12 lines of code 1 class, 3 lines of code
  • 71. class Train(object): def __init__(self, cars): self.cars = cars def __iter__(self): for i in range(self.cars): yield 'car #%s' % (i+1) The pattern just vanished
  • 72. class Train(object): def __init__(self, cars): self.cars = cars def __iter__(self): for i in range(self.cars): yield 'car #%s' % (i+1) “When I see patterns in my programs, I consider it a sign of trouble. The shape of a program should reflect only the problem it needs to solve. Any other regularity in the code is a sign, to me at least, that I'm using abstractions that aren't powerful enough -- often that I'm generating by hand the expansions of some macro that I need to write.” Paul Graham Revenge of the nerds (2002)
  • 73. Generator expression (genexp) >>> g = (c for c in 'ABC') >>> g <generator object <genexpr> at 0x10045a410> >>> for l in g: ... print(l) ... A B C >>>
  • 74. @ramalhoorg • When evaluated, returns a generator object >>> g = (n for n in [1, 2, 3]) >>> g <generator object <genexpr> at 0x...> >>> next(g) 1 >>> next(g) 2 >>> next(g) 3 >>> next(g) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration Generator expression (genexp)
  • 75. for car in train: • calls iter(train) to obtain a generator • makes repeated calls to next(generator) until the function returns, which raises StopIteration class Train(object): def __init__(self, cars): self.cars = cars def __iter__(self): for i in range(self.cars): # index 2 is car #3 yield 'car #%s' % (i+1) Train with generator function 1 1 2 >>> train = Train(3) >>> for car in train: ... print(car) car #1 car #2 car #3 2
  • 76. for car in train: • calls iter(train) to obtain a generator • makes repeated calls to next(generator) until the function returns, which raises StopIteration 1 2 class Train(object): def __init__(self, cars): self.cars = cars def __iter__(self): return ('car #%s' % (i+1) for i in range(self.cars)) Train with generator expression >>> train = Train(3) >>> for car in train: ... print(car) car #1 car #2 car #3
  • 77. class Train(object): def __init__(self, cars): self.cars = cars def __iter__(self): return ('car #%s' % (i+1) for i in range(self.cars)) Generator function x genexpclass Train(object): def __init__(self, cars): self.cars = cars def __iter__(self): for i in range(self.cars): yield 'car #%s' % (i+1)
  • 78. @ramalhoorg Built-in functions that return iterables, iterators or generators • dict • enumerate • frozenset • list • reversed • set • tuple 78
  • 79. @ramalhoorg • boundless generators • count(), cycle(), repeat() • generators which combine several iterables: • chain(), tee(), izip(), imap(), product(), compress()... • generators which select or group items: • compress(), dropwhile(), groupby(), ifilter(), islice()... • generators producing combinations of items: • product(), permutations(), combinations()... The itertools module Don’t reinvent the wheel, use itertools! this was not reinvented: ported from Haskell great for MapReduce
  • 80. @ramalhoorg Generators in Python 3 • Several functions and methods of the standard library that used to return lists, now return generators and other lazy iterables in Python 3 • dict.keys(), dict.items(), dict.values()... • range(...) • like xrange in Python 2.x (more than a generator) • If you really need a list, just pass the generator to the list constructor. Eg.: list(range(10)) 80
  • 81. @ramalhoorg A practical example using generator functions • Generator functions to decouple reading and writing logic in a database conversion tool designed to handle large datasets https://github.com/ramalho/isis2json 81
  • 85. @ramalhoorg But what if we need to read another format?
  • 86. @ramalhoorg Functions in the script • iterMstRecords* • iterIsoRecords* • writeJsonArray • main * generator functions
  • 88. main: determine input format selected generator function is passed as an argument input generator function is selected based on the input file extension
  • 90. writeJsonArray: iterates over one of the input generator functions selected generator function received as an argument... and called to produce input generator
  • 92. @ramalhoorg iterIsoRecords yields one record, structured as a dict creates a new dict in each iteration 92
  • 94. iterIsoRecordsiterMstRecords yields one record, structured as a dict creates a new dict in each iteration
  • 98. @ramalhoorg We did not cover • other generator methods: • gen.close(): causes a GeneratorExit exception to be raised within the generator body, at the point where it is paused • gen.throw(e): causes any exception e to be raised within the generator body, at the point it where is paused Mostly useful for long-running processes. Often not needed in batch processing scripts. 98
  • 99. @ramalhoorg We did not cover • generator delegation with yield from • sending data into a generator function with the gen.send(x) method (instead of next(gen)), and using yield as an expression to get the data sent • using generator functions as coroutines not useful in the context of iteration Python ≥ 3.3 “Coroutines are not related to iteration” David Beazley 99
  • 100. @ramalhoorg How to learn generators • Forget about .send() and coroutines: that is a completely different subject. Look into that only after mastering and becoming really confortable using generators for iteration. • Study and use the itertools module • Don’t worry about .close() and .throw() initially. You can be productive with generators without using these methods. • yield from is only available in Python 3.3, and only relevant if you need to use .close() and .throw() 100
  • 101. Q & A Luciano Ramalho luciano@ramalho.org @ramalhoorg https://github.com/ramalho/isis2json