SlideShare una empresa de Scribd logo
1 de 72
Descargar para leer sin conexión
Luciano Ramalho
                              luciano@ramalho.org
                                      @ramalhoorg




Iteráveis, geradores & cia:
o caminho pythonico
Comparando: C e 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
Iteração em Java

class Argumentos {
    public static void main(String[] args) {
        for (int i=0; i < args.length; i++)
            System.out.println(args[i]);
    }
}


             $ java Argumentos alfa bravo charlie
             alfa
             bravo
             charlie                      @ramalhoorg
Iteração em Java ≥1.5                        ano:
                                             2004

 • Enhanced for (for melhorado)
class Argumentos2 {
    public static void main(String[] args) {
        for (String arg : args)
            System.out.println(arg);
    }
}


              $ java Argumentos2 alfa bravo charlie
              alfa
              bravo
              charlie                      @ramalhoorg
Iteração em Java ≥1.5                   ano:
                                        2004

 • Enhanced for (for melhorado)
class Argumentos2 {
    public static void main(String[] args) {
        for (String arg : args)
            System.out.println(arg);
    }
}
                                        ano:
                      import sys        1991

                      for arg in sys.argv:
                          print arg @ramalhoorg
Exemplos de iteração

• Iteração em Python não se limita a tipos primitivos
• Exemplos
 • string
 • arquivo
 • Django QuerySet
                                             @ramalhoorg
>>> 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                             demonstração:
MG Abadia dos Dourados
GO Abadiânia                                   queryset é um
MG Abaeté                                      iterável lazy
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'}]
Em Python o comando for
itera sobre... “iteráveis”
• Definicão preliminar informal:
 • “iterável” = que pode ser iterado
 • assim como:
    “desmontável” = que pode ser desmontado
• Iteráveis podem ser usados em outros contextos
  além do laço for

                                          @ramalhoorg
List comprehension
List comprehensions          ●   Compreensão de lista ou abrangência
                             ●   Exemplo: usar todos os elementos:
•   Expressões que consomem L2 = [n*10 for n in L]
                           – iteráveis e


    produzem listas
     qualquer iterável
    resultado: uma lista

>>> s = 'abracadabra'
>>> l = [ord(c) for c in s]
>>> [ord(c) for c in s]
[97, 98, 114, 97, 99, 97, 100, 97, 98, 114, 97]

                           ≈ notação matemática de conjuntos
                                                     @ramalhoorg
Set & dict comprehensions
• Expressões que consomem iteráveis e
  produzem sets ou dicts


 >>> s = 'abracadabra'
 >>> {c for c in s}
 set(['a', 'r', 'b', 'c', 'd'])
 >>> {c:ord(c) for c in s}
 {'a': 97, 'r': 114, 'b': 98, 'c': 99, 'd': 100}



                                           @ramalhoorg
Tipos iteráveis embutidos
  • basestring   • frozenset
   • str         • list
   • unicode     • set
  • dict         • tuple
  • file          • xrange
                               @ramalhoorg
Funções embutidas que
consomem iteráveis
• all     • max
• any     • min
• filter   • reduce
• iter    • sorted
• len     • sum
• map     • zip
                        @ramalhoorg
Operações com iteráveis
                                       >>>   a, b, c = 'XYZ'
  • Desempacotamento                   >>>
                                       'X'
                                             a

     de tupla                          >>>   b
                                       'Y'

     • em atribuições                  >>>
                                       'Z'
                                       >>>
                                             c

                                             g = (n for n in [1, 2, 3])
     • em chamadas de funções          >>>
                                       >>>
                                             a, b, c = g
                                             a
>>> def soma(a, b):                    1
...     return a + b                   >>>  b
...                                    2
>>> soma(1, 2)                         >>>  c
3                                      3
>>> t = (3, 4)
>>> soma(t)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: soma() takes exactly 2 arguments (1 given)
>>> soma(*t)
                                                               @ramalhoorg
7
Em Python, um iterável é...
• Um objeto a partir do qual a função iter
  consegue obter um iterador.
• A chamada iter(x):
 • invoca x.__iter__() para obter um iterador
 • ou, se x.__iter__ não existe:
   • fabrica um iterador que acessa os itens de x
      sequenciamente: x[0], x[1], x[2] etc.
                                             @ramalhoorg
Trem:
uma sequência de vagões
              trem




    trem[0]
                     Curiosidade:
                     sequências eram chamadas
                     “trains” na linguagem ABC,
                     antecessora de Python
                                      @ramalhoorg
Trem:
uma sequência de vagões
>>> t = Trem(4)
>>> len(t)                           >>> for vagao in t:
4                                    ...   print(vagao)
>>> t[0]                             vagao #1
'vagao #1'                           vagao #2
>>> t[3]                             vagao #3
'vagao #4'                           vagao #4
>>> t[-1]
'vagao #4'
>>> t[4]
Traceback (most recent call last):
  ...
IndexError: vagao inexistente [4]




                                                     @ramalhoorg
Protocolo de sequência
class Trem(object):

    def __init__(self, vagoes):
        self.vagoes = vagoes

    def __getitem__(self, pos):
        indice = pos if pos >= 0 else self.vagoes + pos
        if 0 <= indice < self.vagoes: # indice 2 -> vagao #3
            return 'vagao #%s' % (indice+1)
        else:
            raise IndexError('vagao inexistente [%s]' % pos)




                                                     @ramalhoorg
Protocolo de sequência
 >>> t = Trem(4)
 >>> t[0]
 'vagao #1'
 >>> t[3]
 'vagao #4'            __getitem__
 >>> t[-1]
 'vagao #4'
 >>> for vagao in t:
 ...   print(vagao)
 vagao #1
                       __getitem__
 vagao #2
 vagao #3
 vagao #4




                                @ramalhoorg
Protocolo de sequência
   • protocolo é uma interface informal
    • pode se implementado parcialmente
class Trem(object):

    def __init__(self, num_vagoes):
        self.num_vagoes = num_vagoes

    def __getitem__(self, pos):
        indice = pos if pos >= 0 else self.num_vagoes + pos
        if 0 <= indice < self.num_vagoes: # indice 2 -> vagao #3
            return 'vagao #%s' % (indice+1)
        else:
            raise IndexError('vagao inexistente [%s]' % pos)

                                                      @ramalhoorg
Sequence
  ABC
   • Abstract Base Class
from collections import Sequence

class Trem(Sequence):

    def __init__(self, vagoes):
        self.vagoes = vagoes

    def __len__(self):
        return self.vagoes

    def __getitem__(self, pos):
        indice = pos if pos >= 0 else self.vagoes + pos
        if 0 <= indice < self.vagoes: # indice 2 -> vagao #3
            return 'vagao #%s' % (indice+1)
        else:
            raise IndexError('vagao inexistente [%s]' % pos) @ramalhoorg
Herança de
 Sequence
>>> t = Trem(4)
>>> 'vagao #2' in t
True
>>> 'vagao #5' in t
False
>>> for i in reversed(t): print i
...
vagao #4                             from collections import Sequence
vagao #3
vagao #2                             class Trem(Sequence):
vagao #1
>>> t.index('vagao #2')                  def __init__(self, vagoes):
1                                            self.vagoes = vagoes
>>> t.index('vagao #7')
Traceback (most recent call last):       def __len__(self):
                                             return self.vagoes
  ...
ValueError                                               @ramalhoorg
                                         def __getitem__(self, pos):
Interface
Iterable
• Iterable provê um método
  __iter__

• O método __iter__ devolve
  uma instância de Iterator
• Você normalmente não chama __iter__, quem
  chama é o Python
 • mas se precisar, use iter(x)
                                        @ramalhoorg
Interface
Iterator
• Iterable provê um método
  next         Python 2
  ou
  __next__     Python 3

• next/__next__ devolve o próximo item
• Você normalmente não chama __next__
 • mas se precisar, use next(x) Python ≥ 2.6
                                          @ramalhoorg
Iterator é...
• um padrão de projeto


                         Design Patterns
                         Gamma, Helm, Johnson & Vlissides
                         Addison-Wesley,
                         ISBN 0-201-63361-2




                                              @ramalhoorg
Head First
Design Patterns
Poster
O'Reilly,
ISBN 0-596-10214-3




                     @ramalhoorg
O padrão
Iterator permite
acessar os itens
de uma coleção
sequencialmente,
isolando o cliente
da implementação
da coleção.
Head First
Design Patterns
Poster
O'Reilly,
ISBN 0-596-10214-3




                     @ramalhoorg
Trem                 class Trem(object):

 com                      def __init__(self, vagoes):
                              self.vagoes = vagoes

 iterator                 def __iter__(self):
                              return IteradorTrem(self.vagoes)

                      class IteradorTrem(object):

                          def __init__(self, vagoes):
                              self.atual = 0
                              self.ultimo_vagao = vagoes - 1

                          def next(self):
                              if self.atual <= self.ultimo_vagao:
>>> t = Trem(4)                   self.atual += 1
>>> for vagao in t:               return 'vagao #%s' % (self.atual)
...   print(vagao)            else:
vagao #1
                                  raise StopIteration()
vagao #2
vagao #3
vagao #4                                                 @ramalhoorg
Trem
                      class Trem(object):

                          def __init__(self, vagoes):
                              self.vagoes = vagoes



 com                      def __iter__(self):
                              return IteradorTrem(self.vagoes)




 iterator
                      class IteradorTrem(object):

                          def __init__(self, vagoes):
                              self.atual = 0
                              self.ultimo_vagao = vagoes - 1

                          def next(self):
                              if self.atual <= self.ultimo_vagao:
                                  self.atual += 1
                                  return 'vagao #%s' % (self.atual)

      iter(t)                 else:
                                  raise StopIteration()


                      • for vagao in t:
>>> t = Trem(4)
>>> for vagao in t:
                       • invoca iter(t)
...   print(vagao)
vagao #1
                          • devolve IteradorTrem
vagao #2
vagao #3
vagao #4                                                         @ramalhoorg
Trem
                       class Trem(object):

                           def __init__(self, vagoes):
                               self.vagoes = vagoes



 com                       def __iter__(self):
                               return IteradorTrem(self.vagoes)




 iterator
                       class IteradorTrem(object):

                           def __init__(self, vagoes):
                               self.atual = 0
                               self.ultimo_vagao = vagoes - 1

                           def next(self):
                               if self.atual <= self.ultimo_vagao:
                                   self.atual += 1
                                   return 'vagao #%s' % (self.atual)

 next(it_trem)                 else:
                                   raise StopIteration()


                      • for vagao in t:
>>> t = Trem(4)
>>> for vagao in t:
                       • invoca iter(t)
...   print(vagao)
vagao #1
                          • devolve IteradorTrem
vagao #2
vagao #3               • invoca next(it_trem) até que
vagao #4                    ele levante StopIteration
                                                    @ramalhoorg
Em Python, um iterável é...
• Um objeto a partir do qual a função iter
  consegue obter um iterador.
• A chamada iter(x):       interface Iterable

 • invoca x.__iter__() para obter um iterador
 • ou, se x.__iter__ não existe:
   • fabrica um iterador que acessa os itens de x
      sequenciamente: x[0], x[1], x[2] etc.
           protocolo de sequência            @ramalhoorg
Iteração em C (exemplo 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
Iteração em Python (ex. 2)
                                     não
import sys
                                  Pythonico!
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                 @ramalhoorg
Iteração em Python (ex. 2)
import sys                        Pythonico!
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                 @ramalhoorg
Iteração em Python (ex. 2)
import sys                              isso constroi
                                         um gerador
for i, arg in enumerate(sys.argv):
    print i, ':', arg
o gerador produz uma
                            o gerador é um iterável preguiçoso!
  tupla (indice, item)
     sob demanda $ python args2.py alfa bravo charlie
    a cada iteração 0 : args2.py
                   1 : alfa
                   2 : bravo
                   3 : charlie                          @ramalhoorg
Como                     >>> e = enumerate('Turing')

funciona                 >>> e
                         <enumerate object at 0x...>
                         >>> next(e)

enumerate                (0, 'T')
                         >>> next(e) constroi
                                  isso
                         (1, 'u') um gerador
                         >>> next(e)
     enumerate           (2, 'r')
      constroi           >>> next(e)
     um gerador          (3, 'i')
                         >>> next(e)
o gerador produz uma     (4, 'n')
  tupla (indice, item)   >>> next(e)
    a cada next(e)       (5, 'g')
                         >>> next(e)
                         Traceback (most recent...):
                           ...
                         StopIteration        @ramalhoorg
Iterator x generator
• Gerador é uma generalização do iterador
• Por definição, um objeto iterador produz itens
  iterando sobre outro objeto (alguma coleção)
• Um gerador é um iterável que produz itens sem
  necessariamente acessar uma coleção
 • ele pode iterar sobre outro objeto mas também
    pode gerar itens por contra própria, sem
    qualquer dependência externa (ex. Fibonacci)
                                            @ramalhoorg
Função                  >>> def gen_123():
                        ...     yield 1

geradora                ...
                        ...
                        ...
                                yield 2
                                yield 3

                        >>> for i in gen_123(): print(i)
                        1
                        2
                        3
• Quaquer função        >>> g = gen_123()
                        >>> g
  que tenha a palavra   <generator object gen_123 at ...>
                        >>> next(g)
  reservada yield em    1
  seu corpo é uma       >>> next(g)
                        2
  função geradora       >>> next(g)
                        3
                        >>> next(g)
                        Traceback (most recent call last):
                        ...
                        StopIteration            @ramalhoorg
Objeto                 >>> def gen_123():
                       ...     yield 1

gerador                ...
                       ...
                       ...
                               yield 2
                               yield 3

                       >>> for i in gen_123(): print(i)
                       1

• Quando invocada, a
                       2
                       3
                       >>> g = gen_123()
  função geradora      >>> g
  devolve um           <generator object gen_123 at ...>
                       >>> next(g)
  objeto gerador       1
                       >>> next(g)
                       2
                       >>> next(g)
                       3
                       >>> next(g)
                       Traceback (most recent call last):
                       ...
                       StopIteration            @ramalhoorg
Objeto                    >>> def gen_123():
                          ...     yield 1

gerador                   ...
                          ...
                          ...
                                  yield 2
                                  yield 3

                          >>> for i in gen_123(): print(i)
• O objeto gerador é      1
                          2
  um iterável,            3
  implementa              >>> g = gen_123()
                          >>> g
  .next()      Python 2   <generator object gen_123 at ...>
                          >>> next(g)
  ou                      1
  .__next__() Python 3    >>> next(g)
                          2

• Use next(gerador)       >>> next(g)
                          3
                          >>> next(g)
           Python ≥ 2.6   Traceback (most recent call last):
                          ...
                          StopIteration            @ramalhoorg
>>> def gen_ab():
...
...
...
        print('iniciando...')
        yield 'A'
        print('agora vem B:')
                                     Como
                                     funciona
...     yield 'B'
...     print('FIM.')
...
>>> for s in gen_ab(): print(s)
iniciando...
A                                    • Invocar uma
agora vem B:
B
                                       função geradora
FIM.                                   produz um
>>> g = gen_ab()
>>> g # doctest: +ELLIPSIS             objeto gerador
<generator object gen_ab at 0x...>
>>> next(g)
iniciando...                         • O corpo da função só
'A'                                    começa a ser
>>> next(g)
agora vem B:                           executado quando se
'B'
>>> next(g)
                                       invoca next
Traceback (most recent call last):
...
StopIteration                                        @ramalhoorg
>>> def gen_ab():
...
...
...
        print('iniciando...')
        yield 'A'
        print('agora vem B:')
                                     Como
                                     funciona
...     yield 'B'
...     print('FIM.')
...
>>> for s in gen_ab(): print(s)
iniciando...
A
agora vem B:
B                                    • Quando next(g) é
FIM.                                   invocado, o corpo da
>>> g = gen_ab()
>>> g # doctest: +ELLIPSIS             função é executado
<generator object gen_ab at 0x...>
>>> next(g)
                                       só até o primeiro
iniciando...                           yield
'A'
>>> next(g)
agora vem B:
'B'
>>> next(g)
Traceback (most recent call last):
...
StopIteration                                       @ramalhoorg
>>> def gen_ab():
...
...
...
        print('iniciando...')
        yield 'A'
        print('agora vem B:')
                                     Como
                                     funciona
...     yield 'B'
...     print('FIM.')
...
>>> for s in gen_ab(): print(s)
iniciando...
A
agora vem B:
B                                    • Invocando next(g)
FIM.                                   novamente, a
>>> g = gen_ab()
>>> g # doctest: +ELLIPSIS             execução avança até
<generator object gen_ab at 0x...>
>>> next(g)
                                       o próximo yield
iniciando...
'A'
>>> next(g)
agora vem B:
'B'
>>> next(g)
Traceback (most recent call last):
...
StopIteration                                      @ramalhoorg
Trem c/ função geradora
                      class Trem(object):

                          def __init__(self, vagoes):
                              self.vagoes = vagoes

                          def __iter__(self):
                              for i in range(self.vagoes):
      iter(t)                     yield 'vagao #%s' % (i+1)

                        • for vagao in t:
>>> t = Trem(4)
>>> for vagao in t:
                         • invoca iter(t)
...   print(vagao)
vagao #1
                            • devolve gerador
vagao #2
vagao #3                 • invoca next(gerador) até que
vagao #4                     ele levante StopIteration
                                                     @ramalhoorg
Iterador clássico x gerador
                                           class Trem(object):

                                                def __init__(self, vagoes):
class Trem(object):                                 self.vagoes = vagoes

    def __init__(self, vagoes):                 def __iter__(self):
        self.vagoes = vagoes                        for i in range(self.vagoes):
                                                        yield 'vagao #%s' % (i+1)
    def __iter__(self):
        return IteradorTrem(self.vagoes)
                                                       1 classe,
class IteradorTrem(object):
                                                       3 linhas de código
    def __init__(self, vagoes):
        self.atual = 0
        self.ultimo_vagao = vagoes - 1

    def next(self):
        if self.atual <= self.ultimo_vagao:
            self.atual += 1                       2 classes,
            return 'vagao #%s' % (self.atual)
        else:                                     12 linhas de código
            raise StopIteration()
Iterador clássico x gerador
                                           class Trem(object):

                                                def __init__(self, vagoes):
class Trem(object):                                 self.vagoes = vagoes

    def __init__(self, vagoes):                 def __iter__(self):
        self.vagoes = vagoes                        for i in range(self.vagoes):
                                                        yield 'vagao #%s' % (i+1)
    def __iter__(self):
        return IteradorTrem(self.vagoes)

class IteradorTrem(object):
                                                           O gerador
    def __init__(self, vagoes):                            administra
        self.atual = 0
        self.ultimo_vagao = vagoes - 1                     o contexto
    def next(self):
                                                           para você
        if self.atual <= self.ultimo_vagao:
            self.atual += 1
            return 'vagao #%s' % (self.atual)
        else:
            raise StopIteration()
Expressão geradora
(genexp)
 >>> g = (c for c in 'ABC')
 >>> for l in g:
 ...     print l
 ...
 A
 B
 C
 >>> g = (c for c in 'ABC')
 >>> g
 <generator object <genexpr> at 0x10045a410>


                                        @ramalhoorg
Expressão            >>> g = (c for c in 'ABC')

geradora             >>> for l in g:
                     ...
                     ...
                             print l

                     A
                     B
                     C

• Quando avaliada,
                     >>> g = (c for c in 'ABC')
                     >>> g
                     <generator object <genexpr> at
  devolve um         0x10045a410>
  objeto gerador     >>> next(g)
                     'A'
                     >>> next(g)
                     'B'
                     >>> next(g)
                     'C'
                     >>> next(g)
                     Traceback (most recent call last):
                       File "<stdin>", line 1, in <module>
                     StopIteration
                                                 @ramalhoorg
Trem c/ expressão geradora
                  class Trem(object):

                      def __init__(self, num_vagoes):
                          self.num_vagoes = num_vagoes

                      def __iter__(self):
                          return ('vagao #%s' % (i+1)
                                      for i in range(self.num_vagoes))

      iter(t)
                         •   for vagao in t:

>>> t = Trem(4)
>>> for vagao in t:
                             •   invoca iter(t)
...   print(vagao)
vagao #1
                                 •   devolve gerador
vagao #2
vagao #3                     •   invoca gerador.next() até que
vagao #4                         ele levante StopIteration @ramalhoorg
Função geradora x genexp
class Trem(object):

    def __init__(self, vagoes):
        self.vagoes = vagoes

    def __iter__(self):
        for i in range(self.vagoes):
            yield 'vagao #%s' % (i+1)

class Trem(object):

    def __init__(self, num_vagoes):
        self.num_vagoes = num_vagoes

    def __iter__(self):
        return ('vagao #%s' % (i+1) for i in range(self.num_vagoes))


                                                         @ramalhoorg
Construtores embutidos
que consomem e
produzem iteráveis
• dict        • reversed
• enumerate   • set
• frozenset   • tuple
• list
                           @ramalhoorg
Módulo itertools
• geradores (potencialmente) infinitos
 • count(), cycle(), repeat()
• geradores que combinam vários iteráveis
 • chain(), tee(), izip(), imap(), product(), compress()...
• geradores que selecionam ou agrupam itens:
 • compress(), dropwhile(), groupby(), ifilter(), islice()...
• Iteradores que produzem combinações
 • product(), permutations(), combinations()...    @ramalhoorg
Geradores em Python 3
• Várias funções e métodos da biblioteca padrão
  que devolviam listas agora devolvem geradores:
  •    dict.keys(), dict.items(), dict.values()...

  •    range(...)

      • como xrange no Py 2 (mais que um gerador)
• Quando precisar de uma lista, basta passar o
  gerador para o construtor de list:
                     list(range(10))

                                             @ramalhoorg
Exemplo prático com
funções geradoras
• Funções geradoras para desacoplar laços de
  leitura e escrita em uma ferramenta para
  conversão de bases de dados semi-estruturadas


https://github.com/ramalho/isis2json


                                           @ramalhoorg
Laço principal escreve
arquivo JSON




                         @ramalhoorg
Um outro laço lê os
registros a converter




                        @ramalhoorg
Implementação possível:
o mesmo laço lê e grava




                      @ramalhoorg
Mas e a lógica para ler
outro formato?




                          @ramalhoorg
Funções
do script
 • iterMstRecords*
 • iterIsoRecords*
 • writeJsonArray
 • main	

      * funções geradoras
                            @ramalhoorg
Função main:
leitura dos
argumentos




               @ramalhoorg
Função main: seleção
do formato escolha dadepende geradora
               de leitura
                          função
                                 do
de entrada     formato de entrada




                    função geradora escolhida
                    é passada como argumento
                                      @ramalhoorg
writeJsonArray:
escrever
registros
em JSON



                  @ramalhoorg
writeJsonArray:
itera sobre umas das
funções geradoras




                       @ramalhoorg
iterIsoRecords:
ler registros     função geradora!


de arquivo
ISO-2709



                            @ramalhoorg
iterIsoRecords
                        cria um novo dict
                        a cada iteração




                 produz (yield) registro
                 na forma de um dict @ramalhoorg
iterMstRecords:   função geradora!

ler registros
de arquivo
ISIS .MST



                             @ramalhoorg
iterMstRecords
iterIsoRecords
                    cria um novo dict
                    a cada iteração




             produz (yield) registro
             na forma de um dict @ramalhoorg
Geradores na prática




                       @ramalhoorg
Geradores na prática




                       @ramalhoorg
Geradores na prática




                       @ramalhoorg
Faltou apresentar...
• Envio de dados para um gerador através do
  método .send() (em vez de .next()),
  e uso de yield como uma     .send() não costuma
  expressão para obter o dado ser usado no contexto
  enviado                     de iteração mas em
                              pipelines
• Uso de funções geradoras como co-rotinas
               “Coroutines are not related to iteration”
                                         David Beazley
                                               @ramalhoorg
Faltou apresentar...
• Envio de dados para um gerador através do
  método .send() (em vez de .next()),
  e uso de yield como uma     .send() não costuma
  expressão para obter o dado ser usado no contexto
  enviado                     de iteração mas em
                              pipelines
• Uso de funções geradoras como co-rotinas
              “Co-rotinas não têm relação com iteração”
                                         David Beazley
                                              @ramalhoorg
Oficinas Turing:
computação para programadores
 • Próximos lançamentos:
   • 1ª turma de Python para quem usa Django
   • 3ª turma de Objetos Pythonicos
   • 4ª turma de Python para quem sabe Python
   Para saber mais sobre estes cursos ONLINE
                    escreva para:
           ramalho@turing.com.br
 Turing.com.br

Más contenido relacionado

La actualidad más candente

La actualidad más candente (19)

Python e django na prática
Python e django na práticaPython e django na prática
Python e django na prática
 
Python 02
Python 02Python 02
Python 02
 
Python 01
Python 01Python 01
Python 01
 
Aprendendo ruby
Aprendendo rubyAprendendo ruby
Aprendendo ruby
 
Curso de Python e Django
Curso de Python e DjangoCurso de Python e Django
Curso de Python e Django
 
Python 03
Python 03Python 03
Python 03
 
Postgresql + Python = Power!
Postgresql + Python = Power!Postgresql + Python = Power!
Postgresql + Python = Power!
 
Curso java 06 - mais construtores, interfaces e polimorfismo
Curso java   06 - mais construtores, interfaces e polimorfismoCurso java   06 - mais construtores, interfaces e polimorfismo
Curso java 06 - mais construtores, interfaces e polimorfismo
 
Programando com Python
Programando com PythonProgramando com Python
Programando com Python
 
Desenvolvimento iOS - Aula 1
Desenvolvimento iOS - Aula 1Desenvolvimento iOS - Aula 1
Desenvolvimento iOS - Aula 1
 
Python: programação divertida novamente
Python: programação divertida novamentePython: programação divertida novamente
Python: programação divertida novamente
 
Curso java 01 - molhando os pés com java
Curso java   01 - molhando os pés com javaCurso java   01 - molhando os pés com java
Curso java 01 - molhando os pés com java
 
Javafx Introdução
Javafx IntroduçãoJavafx Introdução
Javafx Introdução
 
Curso de Java: Introdução a lambda e Streams
Curso de Java: Introdução a lambda e StreamsCurso de Java: Introdução a lambda e Streams
Curso de Java: Introdução a lambda e Streams
 
Python
PythonPython
Python
 
Atualização Java 8 (2014)
Atualização Java 8 (2014)Atualização Java 8 (2014)
Atualização Java 8 (2014)
 
Jython no JavaOne Latin America 2011
Jython no JavaOne Latin America 2011Jython no JavaOne Latin America 2011
Jython no JavaOne Latin America 2011
 
Introducao Google GO
Introducao Google GOIntroducao Google GO
Introducao Google GO
 
Palestra python
Palestra pythonPalestra python
Palestra python
 

Destacado

Otimizando sites com o nosql redis
Otimizando sites com o nosql redisOtimizando sites com o nosql redis
Otimizando sites com o nosql redisAllisson Azevedo
 
Consumindo API's OAuth{1,2} com Python
Consumindo API's OAuth{1,2} com PythonConsumindo API's OAuth{1,2} com Python
Consumindo API's OAuth{1,2} com PythonAllisson Azevedo
 
Tarefas Assíncronas com Django e Celery
Tarefas Assíncronas com Django e CeleryTarefas Assíncronas com Django e Celery
Tarefas Assíncronas com Django e CeleryAllisson Azevedo
 
Customizando Admin do Django
Customizando Admin do DjangoCustomizando Admin do Django
Customizando Admin do DjangoGustavo Carvalho
 
Introdução a linguagem Go
Introdução a linguagem GoIntrodução a linguagem Go
Introdução a linguagem GoAllisson Azevedo
 
Deploy completo de uma aplicação Django
Deploy completo de uma aplicação DjangoDeploy completo de uma aplicação Django
Deploy completo de uma aplicação DjangoAllisson Azevedo
 

Destacado (9)

Otimizando sites com o nosql redis
Otimizando sites com o nosql redisOtimizando sites com o nosql redis
Otimizando sites com o nosql redis
 
Consumindo API's OAuth{1,2} com Python
Consumindo API's OAuth{1,2} com PythonConsumindo API's OAuth{1,2} com Python
Consumindo API's OAuth{1,2} com Python
 
Tarefas Assíncronas com Django e Celery
Tarefas Assíncronas com Django e CeleryTarefas Assíncronas com Django e Celery
Tarefas Assíncronas com Django e Celery
 
Python Nordeste 2016
Python Nordeste 2016Python Nordeste 2016
Python Nordeste 2016
 
Customizando Admin do Django
Customizando Admin do DjangoCustomizando Admin do Django
Customizando Admin do Django
 
Wiki-wiki S/A
Wiki-wiki S/AWiki-wiki S/A
Wiki-wiki S/A
 
Introdução a linguagem Go
Introdução a linguagem GoIntrodução a linguagem Go
Introdução a linguagem Go
 
Deploy completo de uma aplicação Django
Deploy completo de uma aplicação DjangoDeploy completo de uma aplicação Django
Deploy completo de uma aplicação Django
 
Docker + Django
Docker + DjangoDocker + Django
Docker + Django
 

Similar a Iteraveis e geradores

Introdução à Linguagem de programação Python
Introdução à Linguagem de programação PythonIntrodução à Linguagem de programação Python
Introdução à Linguagem de programação Pythondmmartins
 
IEEEweek 2017 @ DETI Univ. Aveiro - Workshop Python
IEEEweek 2017 @ DETI Univ. Aveiro - Workshop PythonIEEEweek 2017 @ DETI Univ. Aveiro - Workshop Python
IEEEweek 2017 @ DETI Univ. Aveiro - Workshop PythonDiogo Gomes
 
TDC2016SP - Trilha Node.Js
TDC2016SP - Trilha Node.JsTDC2016SP - Trilha Node.Js
TDC2016SP - Trilha Node.Jstdc-globalcode
 
Introdução a linguagem Python
Introdução a linguagem PythonIntrodução a linguagem Python
Introdução a linguagem PythonLuciano Ramalho
 
O que mudou no Ruby 1.9
O que mudou no Ruby 1.9O que mudou no Ruby 1.9
O que mudou no Ruby 1.9Nando Vieira
 
O que é que o Java não tem?
O que é que o Java não tem?O que é que o Java não tem?
O que é que o Java não tem?Denis Costa
 
Python 3.x - Ihh.. E agora ? Como faço ?
Python 3.x - Ihh.. E agora ? Como faço ?Python 3.x - Ihh.. E agora ? Como faço ?
Python 3.x - Ihh.. E agora ? Como faço ?Marcel Caraciolo
 
Estruturas de dados em Python
Estruturas de dados em PythonEstruturas de dados em Python
Estruturas de dados em PythonRicardo Paiva
 
(2013-05-20) [DevInSampa] AudioLazy - DSP expressivo e em tempo real para o P...
(2013-05-20) [DevInSampa] AudioLazy - DSP expressivo e em tempo real para o P...(2013-05-20) [DevInSampa] AudioLazy - DSP expressivo e em tempo real para o P...
(2013-05-20) [DevInSampa] AudioLazy - DSP expressivo e em tempo real para o P...Danilo J. S. Bellini
 
Ruby - Criando código para máquinas e humanos
Ruby - Criando código para máquinas e humanosRuby - Criando código para máquinas e humanos
Ruby - Criando código para máquinas e humanosGregorio Kusowski
 
Py sintaxe
Py sintaxePy sintaxe
Py sintaxeFlapenta
 
Python e seus desafios
Python e seus desafiosPython e seus desafios
Python e seus desafiosJhonathan Davi
 

Similar a Iteraveis e geradores (20)

Introdução à Linguagem de programação Python
Introdução à Linguagem de programação PythonIntrodução à Linguagem de programação Python
Introdução à Linguagem de programação Python
 
IEEEweek 2017 @ DETI Univ. Aveiro - Workshop Python
IEEEweek 2017 @ DETI Univ. Aveiro - Workshop PythonIEEEweek 2017 @ DETI Univ. Aveiro - Workshop Python
IEEEweek 2017 @ DETI Univ. Aveiro - Workshop Python
 
Python Class
Python ClassPython Class
Python Class
 
TDC2016SP - Trilha Node.Js
TDC2016SP - Trilha Node.JsTDC2016SP - Trilha Node.Js
TDC2016SP - Trilha Node.Js
 
Introdução a linguagem Python
Introdução a linguagem PythonIntrodução a linguagem Python
Introdução a linguagem Python
 
Java4
Java4Java4
Java4
 
O que mudou no Ruby 1.9
O que mudou no Ruby 1.9O que mudou no Ruby 1.9
O que mudou no Ruby 1.9
 
Linguagem R
Linguagem RLinguagem R
Linguagem R
 
Introdução à Linguagem Ruby
Introdução à Linguagem RubyIntrodução à Linguagem Ruby
Introdução à Linguagem Ruby
 
O que é que o Java não tem?
O que é que o Java não tem?O que é que o Java não tem?
O que é que o Java não tem?
 
(2013-05-03) AudioLazy - Slides
(2013-05-03) AudioLazy - Slides(2013-05-03) AudioLazy - Slides
(2013-05-03) AudioLazy - Slides
 
Math
MathMath
Math
 
Python 3.x - Ihh.. E agora ? Como faço ?
Python 3.x - Ihh.. E agora ? Como faço ?Python 3.x - Ihh.. E agora ? Como faço ?
Python 3.x - Ihh.. E agora ? Como faço ?
 
Estruturas de dados em Python
Estruturas de dados em PythonEstruturas de dados em Python
Estruturas de dados em Python
 
(2013-05-20) [DevInSampa] AudioLazy - DSP expressivo e em tempo real para o P...
(2013-05-20) [DevInSampa] AudioLazy - DSP expressivo e em tempo real para o P...(2013-05-20) [DevInSampa] AudioLazy - DSP expressivo e em tempo real para o P...
(2013-05-20) [DevInSampa] AudioLazy - DSP expressivo e em tempo real para o P...
 
Canivete shell
Canivete shellCanivete shell
Canivete shell
 
Canivete shell
Canivete shellCanivete shell
Canivete shell
 
Ruby - Criando código para máquinas e humanos
Ruby - Criando código para máquinas e humanosRuby - Criando código para máquinas e humanos
Ruby - Criando código para máquinas e humanos
 
Py sintaxe
Py sintaxePy sintaxe
Py sintaxe
 
Python e seus desafios
Python e seus desafiosPython e seus desafios
Python e seus desafios
 

Más de Luciano Ramalho

Encapsulamento com descritores
Encapsulamento com descritoresEncapsulamento com descritores
Encapsulamento com descritoresLuciano Ramalho
 
Arduino: hardware hacking & coding dojo
Arduino: hardware hacking & coding dojoArduino: hardware hacking & coding dojo
Arduino: hardware hacking & coding dojoLuciano Ramalho
 
Encapsulamento com Descritores em Python
Encapsulamento com Descritores em PythonEncapsulamento com Descritores em Python
Encapsulamento com Descritores em PythonLuciano Ramalho
 
OO em Python sem sotaque
OO em Python sem sotaqueOO em Python sem sotaque
OO em Python sem sotaqueLuciano Ramalho
 
Python, a arma secreta do Google
Python, a arma secreta do GooglePython, a arma secreta do Google
Python, a arma secreta do GoogleLuciano Ramalho
 
Alex Martelli's Python Design Patterns
Alex Martelli's Python Design PatternsAlex Martelli's Python Design Patterns
Alex Martelli's Python Design PatternsLuciano Ramalho
 
JavaScript agora é sério (TDC 2011)
JavaScript agora é sério (TDC 2011)JavaScript agora é sério (TDC 2011)
JavaScript agora é sério (TDC 2011)Luciano Ramalho
 
JavaScript agora é sério (FISL 2011)
JavaScript agora é sério (FISL 2011)JavaScript agora é sério (FISL 2011)
JavaScript agora é sério (FISL 2011)Luciano Ramalho
 
JavaScript: agora é sério
JavaScript: agora é sérioJavaScript: agora é sério
JavaScript: agora é sérioLuciano Ramalho
 
Porque bibliotecários usam bancos de dados esquisitos
Porque bibliotecários usam bancos de dados esquisitosPorque bibliotecários usam bancos de dados esquisitos
Porque bibliotecários usam bancos de dados esquisitosLuciano Ramalho
 
NoSQL na BIREME: 20 anos de experiência
NoSQL na BIREME: 20 anos de experiênciaNoSQL na BIREME: 20 anos de experiência
NoSQL na BIREME: 20 anos de experiênciaLuciano Ramalho
 

Más de Luciano Ramalho (20)

Mongodb: agregação
Mongodb: agregaçãoMongodb: agregação
Mongodb: agregação
 
Encapsulamento com descritores
Encapsulamento com descritoresEncapsulamento com descritores
Encapsulamento com descritores
 
Arduino: hardware hacking & coding dojo
Arduino: hardware hacking & coding dojoArduino: hardware hacking & coding dojo
Arduino: hardware hacking & coding dojo
 
Encapsulamento com Descritores em Python
Encapsulamento com Descritores em PythonEncapsulamento com Descritores em Python
Encapsulamento com Descritores em Python
 
Dojo com Processing
Dojo com ProcessingDojo com Processing
Dojo com Processing
 
Dojo com Arduino
Dojo com ArduinoDojo com Arduino
Dojo com Arduino
 
Open Library no Mongodb
Open Library no MongodbOpen Library no Mongodb
Open Library no Mongodb
 
OO em Python sem sotaque
OO em Python sem sotaqueOO em Python sem sotaque
OO em Python sem sotaque
 
Modelos ricos
Modelos ricosModelos ricos
Modelos ricos
 
Python, a arma secreta do Google
Python, a arma secreta do GooglePython, a arma secreta do Google
Python, a arma secreta do Google
 
Ensinando OO com Python
Ensinando OO com PythonEnsinando OO com Python
Ensinando OO com Python
 
Alex Martelli's Python Design Patterns
Alex Martelli's Python Design PatternsAlex Martelli's Python Design Patterns
Alex Martelli's Python Design Patterns
 
Dspace em 5 minutos
Dspace em 5 minutosDspace em 5 minutos
Dspace em 5 minutos
 
JavaScript agora é sério (TDC 2011)
JavaScript agora é sério (TDC 2011)JavaScript agora é sério (TDC 2011)
JavaScript agora é sério (TDC 2011)
 
JavaScript agora é sério (FISL 2011)
JavaScript agora é sério (FISL 2011)JavaScript agora é sério (FISL 2011)
JavaScript agora é sério (FISL 2011)
 
Wiki sa-v2
Wiki sa-v2Wiki sa-v2
Wiki sa-v2
 
JavaScript: agora é sério
JavaScript: agora é sérioJavaScript: agora é sério
JavaScript: agora é sério
 
Porque bibliotecários usam bancos de dados esquisitos
Porque bibliotecários usam bancos de dados esquisitosPorque bibliotecários usam bancos de dados esquisitos
Porque bibliotecários usam bancos de dados esquisitos
 
Binary divination
Binary divinationBinary divination
Binary divination
 
NoSQL na BIREME: 20 anos de experiência
NoSQL na BIREME: 20 anos de experiênciaNoSQL na BIREME: 20 anos de experiência
NoSQL na BIREME: 20 anos de experiência
 

Último

ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docxATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx2m Assessoria
 
Padrões de Projeto: Proxy e Command com exemplo
Padrões de Projeto: Proxy e Command com exemploPadrões de Projeto: Proxy e Command com exemplo
Padrões de Projeto: Proxy e Command com exemploDanilo Pinotti
 
ATIVIDADE 1 - SISTEMAS DISTRIBUÍDOS E REDES - 52_2024.docx
ATIVIDADE 1 - SISTEMAS DISTRIBUÍDOS E REDES - 52_2024.docxATIVIDADE 1 - SISTEMAS DISTRIBUÍDOS E REDES - 52_2024.docx
ATIVIDADE 1 - SISTEMAS DISTRIBUÍDOS E REDES - 52_2024.docx2m Assessoria
 
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docxATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx2m Assessoria
 
Luís Kitota AWS Discovery Day Ka Solution.pdf
Luís Kitota AWS Discovery Day Ka Solution.pdfLuís Kitota AWS Discovery Day Ka Solution.pdf
Luís Kitota AWS Discovery Day Ka Solution.pdfLuisKitota
 
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docxATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx2m Assessoria
 
Boas práticas de programação com Object Calisthenics
Boas práticas de programação com Object CalisthenicsBoas práticas de programação com Object Calisthenics
Boas práticas de programação com Object CalisthenicsDanilo Pinotti
 
ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx
ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docxATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx
ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx2m Assessoria
 
Programação Orientada a Objetos - 4 Pilares.pdf
Programação Orientada a Objetos - 4 Pilares.pdfProgramação Orientada a Objetos - 4 Pilares.pdf
Programação Orientada a Objetos - 4 Pilares.pdfSamaraLunas
 

Último (9)

ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docxATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
 
Padrões de Projeto: Proxy e Command com exemplo
Padrões de Projeto: Proxy e Command com exemploPadrões de Projeto: Proxy e Command com exemplo
Padrões de Projeto: Proxy e Command com exemplo
 
ATIVIDADE 1 - SISTEMAS DISTRIBUÍDOS E REDES - 52_2024.docx
ATIVIDADE 1 - SISTEMAS DISTRIBUÍDOS E REDES - 52_2024.docxATIVIDADE 1 - SISTEMAS DISTRIBUÍDOS E REDES - 52_2024.docx
ATIVIDADE 1 - SISTEMAS DISTRIBUÍDOS E REDES - 52_2024.docx
 
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docxATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
 
Luís Kitota AWS Discovery Day Ka Solution.pdf
Luís Kitota AWS Discovery Day Ka Solution.pdfLuís Kitota AWS Discovery Day Ka Solution.pdf
Luís Kitota AWS Discovery Day Ka Solution.pdf
 
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docxATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
 
Boas práticas de programação com Object Calisthenics
Boas práticas de programação com Object CalisthenicsBoas práticas de programação com Object Calisthenics
Boas práticas de programação com Object Calisthenics
 
ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx
ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docxATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx
ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx
 
Programação Orientada a Objetos - 4 Pilares.pdf
Programação Orientada a Objetos - 4 Pilares.pdfProgramação Orientada a Objetos - 4 Pilares.pdf
Programação Orientada a Objetos - 4 Pilares.pdf
 

Iteraveis e geradores

  • 1. Luciano Ramalho luciano@ramalho.org @ramalhoorg Iteráveis, geradores & cia: o caminho pythonico
  • 2. Comparando: C e 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
  • 3. Iteração em Java class Argumentos { public static void main(String[] args) { for (int i=0; i < args.length; i++) System.out.println(args[i]); } } $ java Argumentos alfa bravo charlie alfa bravo charlie @ramalhoorg
  • 4. Iteração em Java ≥1.5 ano: 2004 • Enhanced for (for melhorado) class Argumentos2 { public static void main(String[] args) { for (String arg : args) System.out.println(arg); } } $ java Argumentos2 alfa bravo charlie alfa bravo charlie @ramalhoorg
  • 5. Iteração em Java ≥1.5 ano: 2004 • Enhanced for (for melhorado) class Argumentos2 { public static void main(String[] args) { for (String arg : args) System.out.println(arg); } } ano: import sys 1991 for arg in sys.argv: print arg @ramalhoorg
  • 6. Exemplos de iteração • Iteração em Python não se limita a tipos primitivos • Exemplos • string • arquivo • Django QuerySet @ramalhoorg
  • 7. >>> 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 demonstração: MG Abadia dos Dourados GO Abadiânia queryset é um MG Abaeté iterável lazy 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'}]
  • 8. Em Python o comando for itera sobre... “iteráveis” • Definicão preliminar informal: • “iterável” = que pode ser iterado • assim como: “desmontável” = que pode ser desmontado • Iteráveis podem ser usados em outros contextos além do laço for @ramalhoorg
  • 9. List comprehension List comprehensions ● Compreensão de lista ou abrangência ● Exemplo: usar todos os elementos: • Expressões que consomem L2 = [n*10 for n in L] – iteráveis e produzem listas qualquer iterável resultado: uma lista >>> s = 'abracadabra' >>> l = [ord(c) for c in s] >>> [ord(c) for c in s] [97, 98, 114, 97, 99, 97, 100, 97, 98, 114, 97] ≈ notação matemática de conjuntos @ramalhoorg
  • 10. Set & dict comprehensions • Expressões que consomem iteráveis e produzem sets ou dicts >>> s = 'abracadabra' >>> {c for c in s} set(['a', 'r', 'b', 'c', 'd']) >>> {c:ord(c) for c in s} {'a': 97, 'r': 114, 'b': 98, 'c': 99, 'd': 100} @ramalhoorg
  • 11. Tipos iteráveis embutidos • basestring • frozenset • str • list • unicode • set • dict • tuple • file • xrange @ramalhoorg
  • 12. Funções embutidas que consomem iteráveis • all • max • any • min • filter • reduce • iter • sorted • len • sum • map • zip @ramalhoorg
  • 13. Operações com iteráveis >>> a, b, c = 'XYZ' • Desempacotamento >>> 'X' a de tupla >>> b 'Y' • em atribuições >>> 'Z' >>> c g = (n for n in [1, 2, 3]) • em chamadas de funções >>> >>> a, b, c = g a >>> def soma(a, b): 1 ... return a + b >>> b ... 2 >>> soma(1, 2) >>> c 3 3 >>> t = (3, 4) >>> soma(t) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: soma() takes exactly 2 arguments (1 given) >>> soma(*t) @ramalhoorg 7
  • 14. Em Python, um iterável é... • Um objeto a partir do qual a função iter consegue obter um iterador. • A chamada iter(x): • invoca x.__iter__() para obter um iterador • ou, se x.__iter__ não existe: • fabrica um iterador que acessa os itens de x sequenciamente: x[0], x[1], x[2] etc. @ramalhoorg
  • 15. Trem: uma sequência de vagões trem trem[0] Curiosidade: sequências eram chamadas “trains” na linguagem ABC, antecessora de Python @ramalhoorg
  • 16. Trem: uma sequência de vagões >>> t = Trem(4) >>> len(t) >>> for vagao in t: 4 ... print(vagao) >>> t[0] vagao #1 'vagao #1' vagao #2 >>> t[3] vagao #3 'vagao #4' vagao #4 >>> t[-1] 'vagao #4' >>> t[4] Traceback (most recent call last): ... IndexError: vagao inexistente [4] @ramalhoorg
  • 17. Protocolo de sequência class Trem(object): def __init__(self, vagoes): self.vagoes = vagoes def __getitem__(self, pos): indice = pos if pos >= 0 else self.vagoes + pos if 0 <= indice < self.vagoes: # indice 2 -> vagao #3 return 'vagao #%s' % (indice+1) else: raise IndexError('vagao inexistente [%s]' % pos) @ramalhoorg
  • 18. Protocolo de sequência >>> t = Trem(4) >>> t[0] 'vagao #1' >>> t[3] 'vagao #4' __getitem__ >>> t[-1] 'vagao #4' >>> for vagao in t: ... print(vagao) vagao #1 __getitem__ vagao #2 vagao #3 vagao #4 @ramalhoorg
  • 19. Protocolo de sequência • protocolo é uma interface informal • pode se implementado parcialmente class Trem(object): def __init__(self, num_vagoes): self.num_vagoes = num_vagoes def __getitem__(self, pos): indice = pos if pos >= 0 else self.num_vagoes + pos if 0 <= indice < self.num_vagoes: # indice 2 -> vagao #3 return 'vagao #%s' % (indice+1) else: raise IndexError('vagao inexistente [%s]' % pos) @ramalhoorg
  • 20. Sequence ABC • Abstract Base Class from collections import Sequence class Trem(Sequence): def __init__(self, vagoes): self.vagoes = vagoes def __len__(self): return self.vagoes def __getitem__(self, pos): indice = pos if pos >= 0 else self.vagoes + pos if 0 <= indice < self.vagoes: # indice 2 -> vagao #3 return 'vagao #%s' % (indice+1) else: raise IndexError('vagao inexistente [%s]' % pos) @ramalhoorg
  • 21. Herança de Sequence >>> t = Trem(4) >>> 'vagao #2' in t True >>> 'vagao #5' in t False >>> for i in reversed(t): print i ... vagao #4 from collections import Sequence vagao #3 vagao #2 class Trem(Sequence): vagao #1 >>> t.index('vagao #2') def __init__(self, vagoes): 1 self.vagoes = vagoes >>> t.index('vagao #7') Traceback (most recent call last): def __len__(self): return self.vagoes ... ValueError @ramalhoorg def __getitem__(self, pos):
  • 22. Interface Iterable • Iterable provê um método __iter__ • O método __iter__ devolve uma instância de Iterator • Você normalmente não chama __iter__, quem chama é o Python • mas se precisar, use iter(x) @ramalhoorg
  • 23. Interface Iterator • Iterable provê um método next Python 2 ou __next__ Python 3 • next/__next__ devolve o próximo item • Você normalmente não chama __next__ • mas se precisar, use next(x) Python ≥ 2.6 @ramalhoorg
  • 24. Iterator é... • um padrão de projeto Design Patterns Gamma, Helm, Johnson & Vlissides Addison-Wesley, ISBN 0-201-63361-2 @ramalhoorg
  • 26. O padrão Iterator permite acessar os itens de uma coleção sequencialmente, isolando o cliente da implementação da coleção. Head First Design Patterns Poster O'Reilly, ISBN 0-596-10214-3 @ramalhoorg
  • 27. Trem class Trem(object): com def __init__(self, vagoes): self.vagoes = vagoes iterator def __iter__(self): return IteradorTrem(self.vagoes) class IteradorTrem(object): def __init__(self, vagoes): self.atual = 0 self.ultimo_vagao = vagoes - 1 def next(self): if self.atual <= self.ultimo_vagao: >>> t = Trem(4) self.atual += 1 >>> for vagao in t: return 'vagao #%s' % (self.atual) ... print(vagao) else: vagao #1 raise StopIteration() vagao #2 vagao #3 vagao #4 @ramalhoorg
  • 28. Trem class Trem(object): def __init__(self, vagoes): self.vagoes = vagoes com def __iter__(self): return IteradorTrem(self.vagoes) iterator class IteradorTrem(object): def __init__(self, vagoes): self.atual = 0 self.ultimo_vagao = vagoes - 1 def next(self): if self.atual <= self.ultimo_vagao: self.atual += 1 return 'vagao #%s' % (self.atual) iter(t) else: raise StopIteration() • for vagao in t: >>> t = Trem(4) >>> for vagao in t: • invoca iter(t) ... print(vagao) vagao #1 • devolve IteradorTrem vagao #2 vagao #3 vagao #4 @ramalhoorg
  • 29. Trem class Trem(object): def __init__(self, vagoes): self.vagoes = vagoes com def __iter__(self): return IteradorTrem(self.vagoes) iterator class IteradorTrem(object): def __init__(self, vagoes): self.atual = 0 self.ultimo_vagao = vagoes - 1 def next(self): if self.atual <= self.ultimo_vagao: self.atual += 1 return 'vagao #%s' % (self.atual) next(it_trem) else: raise StopIteration() • for vagao in t: >>> t = Trem(4) >>> for vagao in t: • invoca iter(t) ... print(vagao) vagao #1 • devolve IteradorTrem vagao #2 vagao #3 • invoca next(it_trem) até que vagao #4 ele levante StopIteration @ramalhoorg
  • 30. Em Python, um iterável é... • Um objeto a partir do qual a função iter consegue obter um iterador. • A chamada iter(x): interface Iterable • invoca x.__iter__() para obter um iterador • ou, se x.__iter__ não existe: • fabrica um iterador que acessa os itens de x sequenciamente: x[0], x[1], x[2] etc. protocolo de sequência @ramalhoorg
  • 31. Iteração em C (exemplo 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
  • 32. Iteração em Python (ex. 2) não import sys Pythonico! 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 @ramalhoorg
  • 33. Iteração em Python (ex. 2) import sys Pythonico! 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 @ramalhoorg
  • 34. Iteração em Python (ex. 2) import sys isso constroi um gerador for i, arg in enumerate(sys.argv): print i, ':', arg o gerador produz uma o gerador é um iterável preguiçoso! tupla (indice, item) sob demanda $ python args2.py alfa bravo charlie a cada iteração 0 : args2.py 1 : alfa 2 : bravo 3 : charlie @ramalhoorg
  • 35. Como >>> e = enumerate('Turing') funciona >>> e <enumerate object at 0x...> >>> next(e) enumerate (0, 'T') >>> next(e) constroi isso (1, 'u') um gerador >>> next(e) enumerate (2, 'r') constroi >>> next(e) um gerador (3, 'i') >>> next(e) o gerador produz uma (4, 'n') tupla (indice, item) >>> next(e) a cada next(e) (5, 'g') >>> next(e) Traceback (most recent...): ... StopIteration @ramalhoorg
  • 36. Iterator x generator • Gerador é uma generalização do iterador • Por definição, um objeto iterador produz itens iterando sobre outro objeto (alguma coleção) • Um gerador é um iterável que produz itens sem necessariamente acessar uma coleção • ele pode iterar sobre outro objeto mas também pode gerar itens por contra própria, sem qualquer dependência externa (ex. Fibonacci) @ramalhoorg
  • 37. Função >>> def gen_123(): ... yield 1 geradora ... ... ... yield 2 yield 3 >>> for i in gen_123(): print(i) 1 2 3 • Quaquer função >>> g = gen_123() >>> g que tenha a palavra <generator object gen_123 at ...> >>> next(g) reservada yield em 1 seu corpo é uma >>> next(g) 2 função geradora >>> next(g) 3 >>> next(g) Traceback (most recent call last): ... StopIteration @ramalhoorg
  • 38. Objeto >>> def gen_123(): ... yield 1 gerador ... ... ... yield 2 yield 3 >>> for i in gen_123(): print(i) 1 • Quando invocada, a 2 3 >>> g = gen_123() função geradora >>> g devolve um <generator object gen_123 at ...> >>> next(g) objeto gerador 1 >>> next(g) 2 >>> next(g) 3 >>> next(g) Traceback (most recent call last): ... StopIteration @ramalhoorg
  • 39. Objeto >>> def gen_123(): ... yield 1 gerador ... ... ... yield 2 yield 3 >>> for i in gen_123(): print(i) • O objeto gerador é 1 2 um iterável, 3 implementa >>> g = gen_123() >>> g .next() Python 2 <generator object gen_123 at ...> >>> next(g) ou 1 .__next__() Python 3 >>> next(g) 2 • Use next(gerador) >>> next(g) 3 >>> next(g) Python ≥ 2.6 Traceback (most recent call last): ... StopIteration @ramalhoorg
  • 40. >>> def gen_ab(): ... ... ... print('iniciando...') yield 'A' print('agora vem B:') Como funciona ... yield 'B' ... print('FIM.') ... >>> for s in gen_ab(): print(s) iniciando... A • Invocar uma agora vem B: B função geradora FIM. produz um >>> g = gen_ab() >>> g # doctest: +ELLIPSIS objeto gerador <generator object gen_ab at 0x...> >>> next(g) iniciando... • O corpo da função só 'A' começa a ser >>> next(g) agora vem B: executado quando se 'B' >>> next(g) invoca next Traceback (most recent call last): ... StopIteration @ramalhoorg
  • 41. >>> def gen_ab(): ... ... ... print('iniciando...') yield 'A' print('agora vem B:') Como funciona ... yield 'B' ... print('FIM.') ... >>> for s in gen_ab(): print(s) iniciando... A agora vem B: B • Quando next(g) é FIM. invocado, o corpo da >>> g = gen_ab() >>> g # doctest: +ELLIPSIS função é executado <generator object gen_ab at 0x...> >>> next(g) só até o primeiro iniciando... yield 'A' >>> next(g) agora vem B: 'B' >>> next(g) Traceback (most recent call last): ... StopIteration @ramalhoorg
  • 42. >>> def gen_ab(): ... ... ... print('iniciando...') yield 'A' print('agora vem B:') Como funciona ... yield 'B' ... print('FIM.') ... >>> for s in gen_ab(): print(s) iniciando... A agora vem B: B • Invocando next(g) FIM. novamente, a >>> g = gen_ab() >>> g # doctest: +ELLIPSIS execução avança até <generator object gen_ab at 0x...> >>> next(g) o próximo yield iniciando... 'A' >>> next(g) agora vem B: 'B' >>> next(g) Traceback (most recent call last): ... StopIteration @ramalhoorg
  • 43. Trem c/ função geradora class Trem(object): def __init__(self, vagoes): self.vagoes = vagoes def __iter__(self): for i in range(self.vagoes): iter(t) yield 'vagao #%s' % (i+1) • for vagao in t: >>> t = Trem(4) >>> for vagao in t: • invoca iter(t) ... print(vagao) vagao #1 • devolve gerador vagao #2 vagao #3 • invoca next(gerador) até que vagao #4 ele levante StopIteration @ramalhoorg
  • 44. Iterador clássico x gerador class Trem(object): def __init__(self, vagoes): class Trem(object): self.vagoes = vagoes def __init__(self, vagoes): def __iter__(self): self.vagoes = vagoes for i in range(self.vagoes): yield 'vagao #%s' % (i+1) def __iter__(self): return IteradorTrem(self.vagoes) 1 classe, class IteradorTrem(object): 3 linhas de código def __init__(self, vagoes): self.atual = 0 self.ultimo_vagao = vagoes - 1 def next(self): if self.atual <= self.ultimo_vagao: self.atual += 1 2 classes, return 'vagao #%s' % (self.atual) else: 12 linhas de código raise StopIteration()
  • 45. Iterador clássico x gerador class Trem(object): def __init__(self, vagoes): class Trem(object): self.vagoes = vagoes def __init__(self, vagoes): def __iter__(self): self.vagoes = vagoes for i in range(self.vagoes): yield 'vagao #%s' % (i+1) def __iter__(self): return IteradorTrem(self.vagoes) class IteradorTrem(object): O gerador def __init__(self, vagoes): administra self.atual = 0 self.ultimo_vagao = vagoes - 1 o contexto def next(self): para você if self.atual <= self.ultimo_vagao: self.atual += 1 return 'vagao #%s' % (self.atual) else: raise StopIteration()
  • 46. Expressão geradora (genexp) >>> g = (c for c in 'ABC') >>> for l in g: ... print l ... A B C >>> g = (c for c in 'ABC') >>> g <generator object <genexpr> at 0x10045a410> @ramalhoorg
  • 47. Expressão >>> g = (c for c in 'ABC') geradora >>> for l in g: ... ... print l A B C • Quando avaliada, >>> g = (c for c in 'ABC') >>> g <generator object <genexpr> at devolve um 0x10045a410> objeto gerador >>> next(g) 'A' >>> next(g) 'B' >>> next(g) 'C' >>> next(g) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration @ramalhoorg
  • 48. Trem c/ expressão geradora class Trem(object): def __init__(self, num_vagoes): self.num_vagoes = num_vagoes def __iter__(self): return ('vagao #%s' % (i+1) for i in range(self.num_vagoes)) iter(t) • for vagao in t: >>> t = Trem(4) >>> for vagao in t: • invoca iter(t) ... print(vagao) vagao #1 • devolve gerador vagao #2 vagao #3 • invoca gerador.next() até que vagao #4 ele levante StopIteration @ramalhoorg
  • 49. Função geradora x genexp class Trem(object): def __init__(self, vagoes): self.vagoes = vagoes def __iter__(self): for i in range(self.vagoes): yield 'vagao #%s' % (i+1) class Trem(object): def __init__(self, num_vagoes): self.num_vagoes = num_vagoes def __iter__(self): return ('vagao #%s' % (i+1) for i in range(self.num_vagoes)) @ramalhoorg
  • 50. Construtores embutidos que consomem e produzem iteráveis • dict • reversed • enumerate • set • frozenset • tuple • list @ramalhoorg
  • 51. Módulo itertools • geradores (potencialmente) infinitos • count(), cycle(), repeat() • geradores que combinam vários iteráveis • chain(), tee(), izip(), imap(), product(), compress()... • geradores que selecionam ou agrupam itens: • compress(), dropwhile(), groupby(), ifilter(), islice()... • Iteradores que produzem combinações • product(), permutations(), combinations()... @ramalhoorg
  • 52. Geradores em Python 3 • Várias funções e métodos da biblioteca padrão que devolviam listas agora devolvem geradores: • dict.keys(), dict.items(), dict.values()... • range(...) • como xrange no Py 2 (mais que um gerador) • Quando precisar de uma lista, basta passar o gerador para o construtor de list: list(range(10)) @ramalhoorg
  • 53. Exemplo prático com funções geradoras • Funções geradoras para desacoplar laços de leitura e escrita em uma ferramenta para conversão de bases de dados semi-estruturadas https://github.com/ramalho/isis2json @ramalhoorg
  • 55. Um outro laço lê os registros a converter @ramalhoorg
  • 56. Implementação possível: o mesmo laço lê e grava @ramalhoorg
  • 57. Mas e a lógica para ler outro formato? @ramalhoorg
  • 58. Funções do script • iterMstRecords* • iterIsoRecords* • writeJsonArray • main * funções geradoras @ramalhoorg
  • 60. Função main: seleção do formato escolha dadepende geradora de leitura função do de entrada formato de entrada função geradora escolhida é passada como argumento @ramalhoorg
  • 62. writeJsonArray: itera sobre umas das funções geradoras @ramalhoorg
  • 63. iterIsoRecords: ler registros função geradora! de arquivo ISO-2709 @ramalhoorg
  • 64. iterIsoRecords cria um novo dict a cada iteração produz (yield) registro na forma de um dict @ramalhoorg
  • 65. iterMstRecords: função geradora! ler registros de arquivo ISIS .MST @ramalhoorg
  • 66. iterMstRecords iterIsoRecords cria um novo dict a cada iteração produz (yield) registro na forma de um dict @ramalhoorg
  • 67. Geradores na prática @ramalhoorg
  • 68. Geradores na prática @ramalhoorg
  • 69. Geradores na prática @ramalhoorg
  • 70. Faltou apresentar... • Envio de dados para um gerador através do método .send() (em vez de .next()), e uso de yield como uma .send() não costuma expressão para obter o dado ser usado no contexto enviado de iteração mas em pipelines • Uso de funções geradoras como co-rotinas “Coroutines are not related to iteration” David Beazley @ramalhoorg
  • 71. Faltou apresentar... • Envio de dados para um gerador através do método .send() (em vez de .next()), e uso de yield como uma .send() não costuma expressão para obter o dado ser usado no contexto enviado de iteração mas em pipelines • Uso de funções geradoras como co-rotinas “Co-rotinas não têm relação com iteração” David Beazley @ramalhoorg
  • 72. Oficinas Turing: computação para programadores • Próximos lançamentos: • 1ª turma de Python para quem usa Django • 3ª turma de Objetos Pythonicos • 4ª turma de Python para quem sabe Python Para saber mais sobre estes cursos ONLINE escreva para: ramalho@turing.com.br Turing.com.br