SlideShare ist ein Scribd-Unternehmen logo
1 von 98
Downloaden Sie, um offline zu lesen
Luciano Ramalho
  luciano@ramalho.org




outubro/2012
                                                                ac to
                                                           mp
                Objetos Pythonicos                      co
          Orientação a objetos e padrões de projeto em Python
Conceito: “objeto”
• Um componente de software
  que inclui dados (campos) e
  comportamentos (métodos)


• Em geral, os atributos são
  manipulados pelos métodos do
  próprio objeto (encapsulamento)


         Figuras: bycicle (bicicleta), The Java Tutorial
         http://docs.oracle.com/javase/tutorial/java/concepts/object.html
Terminologia
pythonica
• Objetos possuem atributos
• Os atributos de um objeto
  podem ser:
 •  métodos                 funções associadas

 • atributos de dados                     “campos”


        Figuras: bycicle (bicicleta), The Java Tutorial
        http://docs.oracle.com/javase/tutorial/java/concepts/object.html
Exemplo: um objeto dict
>>> d = {'AM':'Manaus', 'PE':'Recife', 'PR': 'Curitiba'}
>>> d.keys()
['PR', 'AM', 'PE']
>>> d.get('PE')
'Recife'
>>> d.pop('PR')
'Curitiba'
>>> d
{'AM': 'Manaus', 'PE': 'Recife'}
>>> len(d)
2
>>> d.__len__()
2




   • Métodos: keys, get, pop, __len__ etc.
Exemplo: um objeto dict
   • dir revela atributos de um dict
    • atributos de dados e métodos
>>> dir(d)
['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__',
'__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
'__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__',
'__len__', '__lt__', '__ne__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__setitem__',
'__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy',
'fromkeys', 'get', 'has_key', 'items', 'iteritems', 'iterkeys',
'itervalues', 'keys', 'pop', 'popitem', 'setdefault', 'update',
'values']
Exemplo: um objeto dict
                            • Sobrecarga de operadores:
                             • [ ]: __getitem__, __setitem__
>>> d
{'AM': 'Manaus', 'PE': 'Recife'}
>>> d['AM']
'Manaus'
>>> d.__getitem__('AM')
'Manaus'
>>> d['MG'] = 'Belo Horizonte'
>>> d.__setitem__('RJ', 'Rio de Janeiro')
>>> d
{'MG': 'Belo Horizonte', 'AM': 'Manaus', 'RJ': 'Rio de Janeiro', 'PE': 'Recife'}
Exemplo: um objeto dict
    • Atributos de dados: __class__, __doc__
 >>> d.__class__
 <type 'dict'>
 >>> type(d)
 <type 'dict'>
 >>> print d.__doc__
 dict() -> new empty dictionary.
 dict(mapping) -> new dictionary initialized from a mapping object's
     (key, value) pairs.
 dict(seq) -> new dictionary initialized as if via:
     d = {}
     for k, v in seq:
         d[k] = v
 dict(**kwargs) -> new dictionary initialized with the name=value pairs
     in the keyword argument list. For example: dict(one=1, two=2)
Exemplo: outro dict
>>> d = dict()
>>> d.keys()
[]                                       • d = dict()
>>> d.get('bla')
>>> print d.get('bla')
                                           é o mesmo que
None                                       d = {}
>>> d.get('spam')
>>> print d.get('spam')
None
>>> d.pop('ovos')
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
KeyError: 'ovos'
>>> d
{}
>>> len(d)
0
>>> d.__len__()
0
Exercício: construir e
 controlar Tkinter.Label
import Tkinter

relogio = Tkinter.Label()

relogio.pack()
relogio['font'] = 'Helvetica 120 bold'
relogio['text'] = strftime('%H:%M:%S')

from time import strftime

def tic():
    relogio['text'] = strftime('%H:%M:%S')
    
def tac():                               Note: no Tkinter, atributos
    relogio.after(100, tictac)           de dados são acessados
                                         via [ ]:
tac()
relogio.mainloop()                       __getitem__ __setitem__
Tudo é um objeto
• Não existem “tipos primitivos” como em Java
 • desde Python 2.2, dezembro de 2001
          >>> 5 + 3
          8
          >>> 5 .__add__(3)
          8
          >>> type(5)
          <type 'int'>
Tipos embutidos
• Implementados em C, por eficiência
• Comportamentos fixos
• Texto: str, unicode
• Números: int, long, float, complex, bool
• Coleções: list, tuple, dict, set, frozenset
• etc.
Funções são objetos
  >>> def fatorial(n):
  ...     '''devolve n!'''
  ...     return 1 if n < 2 else n * fatorial(n-1)
  ...
  >>> fatorial(5)
  120
  >>> fat = fatorial
  >>> fat
  <function fatorial at 0x1004b5f50>
  >>> fat(42)
  1405006117752879898543142606244511569936384000000000L
  >>> fatorial.__doc__
  'devolve n!'
  >>> fatorial.__name__
  'fatorial'
  >>> fatorial.__code__
  <code object fatorial at 0x1004b84e0, file "<stdin>", line 1>
  >>> fatorial.__code__.co_varnames
  ('n',)
Funções são objetos
>>> fatorial.__code__.co_code
'|x00x00dx01x00jx00x00ox05x00x01dx02x00Sx01|x00x00tx00x00|
x00x00dx02x00x18x83x01x00x14S'
>>> from dis import dis
>>> dis(fatorial.__code__.co_code)
          0 LOAD_FAST           0 (0)
          3 LOAD_CONST          1 (1)
          6 COMPARE_OP          0 (<)

                                              Bytecode da
          9 JUMP_IF_FALSE       5 (to 17)
         12 POP_TOP
         13 LOAD_CONST          2 (2)

    >>
         16 RETURN_VALUE
         17 POP_TOP                           função fatorial
         18 LOAD_FAST           0 (0)
         21 LOAD_GLOBAL         0 (0)
         24 LOAD_FAST           0 (0)
         27 LOAD_CONST          2 (2)
         30 BINARY_SUBTRACT
         31 CALL_FUNCTION       1
         34 BINARY_MULTIPLY
         35 RETURN_VALUE
>>>
Tipagem forte
• O tipo de um objeto nunca muda
• Raramente Python faz conversão automática de
  tipos
    >>> a = 10
    >>> b = '9'
    >>> a + b
    Traceback (most recent    call last):
       File "<stdin>", line   1, in <module>
    TypeError: unsupported    operand type(s) for +: 'int' and 'str'
    >>> a + int(b)
    19
    >>> str(a) + b
    '109'
    >>> 77 * None
    Traceback (most recent    call last):
       File "<stdin>", line   1, in <module>
    TypeError: unsupported    operand type(s) for *: 'int' and 'NoneType'
    >>>
Tipagem dinâmica:
variáveis não têm tipo
>>> def dobro(x):
...      return x * 2
...
>>> dobro(7)
14
>>> dobro(7.1)
14.2
>>> dobro('bom')
'bombom'
>>> dobro([10, 20, 30])
[10, 20, 30, 10, 20, 30]
>>> dobro(None)
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
   File "<stdin>", line 2, in dobro
TypeError: unsupported operand type(s) for *: 'NoneType' and 'int'
Orientação a objetos:
a origem
• Linguagem Simula 1967
 • Noruega: Ole-Johan Dahl e Kristen Nygaard
 • objetos, classes, sub-classes
 • métodos virtuais (funções associadas a objetos
    específicos somente em tempo de execução, e
    não na compilação)
Orientação a objetos:
evolução
• Smalltalk 1980
 • EUA, Xerox PARC (Palo Alto Research Center):
    Alan Kay, Dan Ingalls, Adele Goldberg et. al.
• Terminologia:
 • “Object oriented programming”
 • “message passing” (invocação de métodos),
    “late binding” (métodos virtuais)
Smalltalk 1980
Squeak: Smalltalk livre
Duck typing
• “Se voa como um pato, nada como um pato e
  grasna como um pato, é um pato.”
• Tipagem dinâmica permite duck typing (tipagem
  pato) estilo de programação que evita verificar os
  tipos dos objetos, mas apenas seus métodos
• No exemplo anterior, a função dobro funciona
  com qualquer objeto x que consiga fazer x * 2
 • x implementa o método __mult__(n), para n
    inteiro
Tipagem forte x fraca                                   JavaScript
                                                     (ECMAScript 5)
• Tipagem forte x fraca refere-se a                  em Node.js 0.6
  conversão automática de valores de
  tipos diferente.
• Linguagens de tipagem fraca são muito
                                                    > 10 + '9'
                                                    '109'
                                                    > 10 + '9' * 1
  liberais na mistura entre tipos, e isso é         19
  uma fonte de bugs.                                > '10' + 9 * 1
                                                    '109'

       Veja alguns resultados estranhos obtidos     > 0 == '0'
         com JavaScript, que tem tipagem fraca.     true
                                                    > 0 == ''
     Em Python as três expressões acima geram       true
     TypeError, e as três últimas resultam False.   > '0' == ''
                      Python tem tipagem forte.     false
Tipagem forte x fraca,
dinâmica x estática
• Tipagem forte x fraca refere-se a conversão
  automática de valores de tipos diferentes
• Tipagem dinâmica x estática refere-se à declaração
  dos tipos das variáveis, parâmetros formais e
  valores devolvidos pelas funções
  • Linguagens de tipagem estática exigem a
    declaração dos tipos, ou usam inferência de tipos
    para garantir que uma variável será associada a
    somente a valores de um tipo
Tipagem em linguagens
  Smalltalk   dinâmica   forte
    Python    dinâmica   forte
      Ruby    dinâmica   forte
  C (K&R)     estática   fraca
 C (ANSI)     estática   forte
       Java   estática   forte
        C#    estática   forte
                                     combinação
 JavaScript
      PHP
              dinâmica
              dinâmica
                         fraca
                         fraca   }   perigosa:
                                     bugs sorrateiros
Conversões automáticas
• Python faz algumas (poucas) conversões
  automáticas entre tipos:
 • Promoção de int para float
 • Promoção de str para unicode
  • assume o encoding padrão: ASCII por default
         >>> 6 * 7.0
         42.0
         >>> 'Spam, ' + u'eggs'
         u'Spam, eggs'
         >>>
Tipos são classes
• Para criar um novo tipo de objeto, crie uma classe
• A função type devolve a classe de um objeto
  >>> class Mamifero(object):
  ...     pass
  ...
  >>> kingkong = Mamifero()
  >>> type(kingkong)
  <class '__main__.Mamifero'>
  >>> ClasseDoKingKong = type(kingkong)
  >>> dumbo = ClasseDoKingKong()
  >>> dumbo
  <__main__.Mamifero object at 0x10045dcd0>
  >>> type(dumbo)
  <class '__main__.Mamifero'>
Conceito: “classe”
• Uma categoria, ou tipo, de objeto
 • Uma idéia abstrata, uma forma platônica
• Exemplo: classe “Cão”:
 • Eu digo: “Ontem eu comprei um cão”
   • Você não sabe exatamente qual cão, mas sabe:
     • é um mamífero, quadrúpede, carnívoro
     • pode ser domesticado (normalmente)
     • cabe em um automóvel
Exemplar de cão:
instância da classe Cao




      >>> rex = Cao()   instanciação
instanciação   >>> rex = Cao('Rex')
                                                 >>> rex

 Classe Cao                                      Cao('Rex')
                                                 >>> print rex
                                                 Rex
                                                 >>> rex.qt_patas
class Mamifero(object):                          4
    """lição de casa: implementar"""             >>> rex.latir()
                                                 Rex: Au!
class Cao(Mamifero):
                                                 >>> rex.latir(2)
    qt_patas = 4
    carnivoro = True                             Rex: Au! Au!
    nervoso = False                              >>> rex.nervoso = True
    def __init__(self, nome):                    >>> rex.latir(3)
        self.nome = nome                         Rex: Au! Au! Au! Au! Au! Au!
    def latir(self, vezes=1):
        # quando nervoso, late o dobro
        vezes = vezes + (self.nervoso * vezes)
        print self.nome + ':' + ' Au!' * vezes
    def __str__(self):
        return self.nome
    def __repr__(self):
        return 'Cao({0!r})'.format(self.nome)




                             oopy/exemplos/cao.py
Como atributos são
acessados
• Ao buscar o.a (atributo a do objeto o da classe C),
  o interpretador Python faz o seguinte:
• 1) acessa atributo a da instancia o; caso não exista...
• 2) acessa atributo a da classe C de o
  (type(o) ou o.__class__); caso nao exista...
• 3) busca o atributo a nas superclasses de C,
  conforme a MRO (method resolution order)
Classe Cao em Python
class Mamifero(object):
    """lição de casa: implementar"""
                                                 •   __init__ é o
class Cao(Mamifero):
    qt_patas = 4                                     construtor, ou melhor,
    carnivoro = True
    nervoso = False
                                                     o inicializador

                                                 •
    def __init__(self, nome):
        self.nome = nome
    def latir(self, vezes=1):
                                                     self é o 1º parâmetro
        # quando nervoso, late o dobro               formal em todos os
        vezes = vezes + (self.nervoso * vezes)
        print self.nome + ':' + ' Au!' * vezes       métodos de instância
    def __str__(self):
        return self.nome
    def __repr__(self):
        return 'Cao({0!r})'.format(self.nome)




                             oopy/exemplos/cao.py
>>> rex = Cao('Rex')
                                                         >>> rex

 Classe Cao                                              Cao('Rex')
                                                         >>> print rex
                                                         Rex
                                                         >>> rex.qt_patas
class Mamifero(object):                                  4
    """lição de casa: implementar"""                     >>> rex.latir()
                                                         Rex: Au!
class Cao(Mamifero):                       invocação     >>> rex.latir(2)
    qt_patas = 4                                         Rex: Au! Au!
    carnivoro = True
    nervoso = False


                                                 •
    def __init__(self, nome):
        self.nome = nome
    def latir(self, vezes=1):
                                                       na invocação do
        # quando nervoso, late o dobro                 método, a instância
        vezes = vezes + (self.nervoso * vezes)
        print self.nome + ':' + ' Au!' * vezes         é passada
    def __str__(self):
        return self.nome                               automaticamente
    def __repr__(self):
        return 'Cao({0!r})'.format(self.nome)
                                                       na posição do self


                               oopy/exemplos/cao.py
Classe Cao em Python
class Mamifero(object):
    """lição de casa: implementar"""             •   atributos de dados na
                                                     classe funcionam
class Cao(Mamifero):
    qt_patas = 4                                     como valores default
    carnivoro = True
    nervoso = False                                  para os atributos das
    def __init__(self, nome):
        self.nome = nome
                                                     instâncas

                                                 •
    def latir(self, vezes=1):
        # quando nervoso, late o dobro
        vezes = vezes + (self.nervoso * vezes)
                                                     atributos da instância
        print self.nome + ':' + ' Au!' * vezes       só podem ser
    def __str__(self):
        return self.nome                             acessados via self
    def __repr__(self):
        return 'Cao({0!r})'.format(self.nome)




                             oopy/exemplos/cao.py
Mamifero: superclasse
 de Cao
class Mamifero(object):
                       UML
                                                                  diagrama de classe
    """lição de casa: implementar"""




                                                 especialização
class Cao(Mamifero):




                                                                                       generalização
    qt_patas = 4
    carnivoro = True
    nervoso = False
    def __init__(self, nome):
        self.nome = nome
    def latir(self, vezes=1):
        # quando nervoso, late o dobro
        vezes = vezes + (self.nervoso * vezes)
        print self.nome + ':' + ' Au!' * vezes
    def __str__(self):
        return self.nome
    def __repr__(self):
        return 'Cao({0!r})'.format(self.nome)




                             oopy/exemplos/cao.py
Subclasses de Cao
      • Continuação
         de cao.py
class Pequines(Cao):
    nervoso = True
    
class Mastiff(Cao):
    def latir(self, vezes=1):
        # o mastiff não muda seu latido quando nervoso
        print self.nome + ':' + ' Wuff!' * vezes
        
class SaoBernardo(Cao):
    def __init__(self, nome):
        Cao.__init__(self, nome)
        self.doses = 10                                   Diz a lenda que o cão
    def servir(self):                                     São Bernardo leva um
        if self.doses == 0:                               pequeno barril de conhaque
            raise ValueError('Acabou o conhaque!')
        self.doses -= 1                                   para resgatar viajantes
        msg = '{0} serve o conhaque (restam {1} doses)'   perdidos na neve.
        print msg.format(self.nome, self.doses)
Subclasses                    >>> sansao = SaoBernardo('Sansao')

 de Cao                        >>> sansao.servir()
                               Sansao serve o conhaque (restam 9 doses)
                               >>> sansao.doses = 1
                               >>> sansao.servir()
                               Sansao serve o conhaque (restam 0 doses)
                               >>> sansao.servir()
class Pequines(Cao):           Traceback (most recent call last):
    nervoso = True               ...
    
class Mastiff(Cao):            ValueError: Acabou o conhaque!
    def latir(self, vezes=1):
        # o mastiff não muda seu latido quando nervoso
        print self.nome + ':' + ' Wuff!' * vezes
        
class SaoBernardo(Cao):
    def __init__(self, nome):
        Cao.__init__(self, nome)
        self.doses = 10
    def servir(self):
        if self.doses == 0:
            raise ValueError('Acabou o conhaque!')
        self.doses -= 1
        msg = '{0} serve o conhaque (restam {1} doses)'
        print msg.format(self.nome, self.doses)
Subclasses de Cao
      • Continuação
         de cao.py
class Pequines(Cao):
    nervoso = True
    
class Mastiff(Cao):
    def latir(self, vezes=1):
        # o mastiff não muda seu latido quando nervoso
        print self.nome + ':' + ' Wuff!' * vezes
        
class SaoBernardo(Cao):
    def __init__(self, nome):
        Cao.__init__(self, nome)
        self.doses = 10
    def servir(self):
        if self.doses == 0:
            raise ValueError('Acabou o conhaque!')
        self.doses -= 1
        msg = '{0} serve o conhaque (restam {1} doses)'
        print msg.format(self.nome, self.doses)
Interface
                • Interface é um conceito essencial em OO
                 • não depende de uma palavra reservada
               A interface fornece uma separação entre a
               implementação de uma abstração e seus clientes.
               Ela limita os detalhes de implementação que os
               clientes podem ver.
               Também especifica a funcionalidade que as
               implementações devem prover.

P. S. Canning, W. R. Cook, W. L. Hill, and W. G. Olthoff. 1989. Interfaces for strongly-typed object-
oriented programming. In Conference proceedings on Object-oriented programming systems,
languages and applications (OOPSLA '89). ACM, New York, NY, USA, 457-467.
DOI=10.1145/74877.74924 http://doi.acm.org/10.1145/74877.74924
Interfaces e protocolos
• Em SmallTalk, as interfaces eram chamadas de
  “protocolos”.
 • Não há verificação de interfaces na linguagem,
    mas algumas IDEs (“browsers”) permitem
    agrupar os métodos por protocolo para facilitar
    a leitura
• Um protocolo é uma interface informal, não
  declarada porém implementada por métodos
  concretos
Interfaces em Python
• Conceitualmente, sempre existiram como
  protocolos
• Não havia maneira formal de especificar interfaces
  em Python até a versão 2.5
 • usava-se termos como “uma sequência” ou
    “a file-like object”
• Agora temos ABC (Abstract Base Class)
 • com herança múltipla, como em C++
Exemplo: tômbola
• Sortear um a um
  todos os itens de
  uma coleção finita,
  sem repetir
• A mesma lógica é
  usada em sistemas
  para gerenciar
  banners online
Interface da tômbola

• Carregar itens
• Misturar itens
• Sortear um item
• Indicar se há mais
  itens
Projeto da tômbola




• UML:
 diagrama de classe
TDD: Test Driven Design
• Metodologia de desenvolvimento iterativa na qual,
  para cada funcionalidade nova, um teste é criado
  antes do código a ser implementado
• Esta inversão ajuda o programador a desenvolver
  com disciplina apenas uma funcionalidade de cada
  vez, mantendo o foco no teste que precisa passar
• Cada iteração de teste/implementação deve ser
  pequena e simples: “baby steps” (passinhos de
  bebê)
Doctests
• Um dos módulos para fazer testes automatizados
  na biblioteca padrão de Python
 • o outro módulo é o unittest, da família xUnit
• Doctests foram criados para testar exemplos
  embutidos na documentação
• Usaremos doctests para especificar exercícios
• Exemplo: $ python -m doctest cao.rst
                  oopy/exemplos/cao.rst
Coding Dojo


• Implementação da classe Tombola, com testes
  feitos em Doctest
Implementação da tômbola
                      # coding: utf-8

                      import random

                      class Tombola(object):
                          itens = None

                          def carregar(self, itens):
                              self.itens = list(itens)

                          def carregada(self):
                              return bool(self.itens)

                          def misturar(self):


 • Python 2.2 a 2.7
                              random.shuffle(self.itens)

                          def sortear(self):
                              return self.itens.pop()
Iteração em 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
ano:
Iteração em Java ≥1.5                          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
ano:
Iteração em Java ≥1.5                    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
 • Baralho (em: “OO em Python sem Sotaque”)
      https://slideshare.net/ramalho/
                                 @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]

                                                          @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
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
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 fazendo x[0], x[1], x[2] etc.
                                             @ramalhoorg
Protocolo de sequência
 >>> t = Trem(4)
 >>> len(t)
 4
                       __len__
 >>> t[0]
 'vagao #1'
 >>> t[3]              __getitem__
 'vagao #4'
 >>> t[-1]
 'vagao #4'
 >>> for vagao in t:
 ...   print(vagao)
                       __getitem__
 vagao #1
 vagao #2
 vagao #3
 vagao #4



                                 @ramalhoorg
Protocolo
  de sequência
 • implementação “informal” da interface
class Trem(object):
    def __init__(self, num_vagoes):
        self.num_vagoes = num_vagoes
    def __len__(self):
        return self.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:
                                                        @ramalhoorg
            raise IndexError('vagao inexistente %s' % pos)
Tômbola como sequência
• Permitir contagem
  de itens
• Permitir acesso
  direto a cada item
  pela ordem em que
  foi colocado

Sim, este é um exemplo
forçado... mas daqui a
pouco melhora!
Interface
  Sequence
  • collections.Sequence
from collections import Sequence

class Trem(Sequence):
    def __init__(self, num_vagoes):
        self.num_vagoes = num_vagoes
    def __len__(self):
        return self.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:
                                                        @ramalhoorg
            raise IndexError('vagao inexistente %s' % pos)
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
vagao #3
                                     from collections import Seque
vagao #2
vagao #1
                                     class Trem(Sequence):
>>> t.index('vagao #2')
                                         def __init__(self, num_va
1
                                             self.num_vagoes = num
>>> t.index('vagao #7')
                                         def __len__(self):
Traceback (most recent call last):
                                             return self.num_vagoe
  ...
                                         def __getitem__(self, pos
ValueError                                             @ramalhoorg
                                             indice = pos if pos >
Interface
Iterable

• Iterable provê um método
  __iter__
• O método __iter__ devolve
  uma instância de Iterator



                              @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):
                          def __init__(self, num_vagoes):
                              self.num_vagoes = num_vagoes
                          def __iter__(self):

 com                          return IteradorTrem(self.num_vagoes)

                      class IteradorTrem(object):


 iterator
                          def __init__(self, num_vagoes):
                              self.atual = 0
                              self.ultimo_vagao = num_vagoes - 1
                          def next(self):
                              if self.atual <= self.ultimo_vagao:
                                  self.atual += 1
                                  return 'vagao #%s' % (self.atual)
                              else:
      iter(t)                     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 itrem.next() até que
vagao #4                         ele levante StopIteration @ramalhoorg
Tômbola iterável
• Permitir iteração
  sobre tômbola em
  um laço for,
  devolvendo os itens
  em uma ordem
  sorteada

  Agora o exemplo
  faz mais sentido!
Recapitulando: 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 fazendo 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)
 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                 @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 g123():


geradora
                     ...     yield 1
                     ...     yield 2
                     ...     yield 3
                     ...
                     >>> for i in g123(): print i
                     ...

• Quando invocada,
                     1
                     2
                     3
  devolve um         >>> g = g123()
                     >>> g
  objeto gerador     <generator object g123 at 0x10e385e10>

• O objeto gerador
                     >>> g.next()
                     1
                     >>> g.next()
  é um iterável      2
                     >>> g.next()
                     3
                     >>> g.next()
                     Traceback (most recent call last):
                       File "<stdin>", line 1, in <module>
                     StopIteration                @ramalhoorg
Trem c/ função geradora
                      class Trem(object):
                          def __init__(self, num_vagoes):
                              self.num_vagoes = num_vagoes
                          def __iter__(self):
                              for i in range(self.num_vagoes):
                                  yield 'vagao #%s' % (i+1)
      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
class Trem(object):

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


clássico
                    return IteradorTrem(self.num_vagoes)

            class IteradorTrem(object):
                def __init__(self, num_vagoes):
12 linhas           self.atual = 0
                    self.ultimo_vagao = num_vagoes - 1
de código       def next(self):
                    if self.atual <= self.ultimo_vagao:
                        self.atual += 1
                        return 'vagao #%s' % (self.atual)
                    else:
                        raise StopIteration()

            mesma funcionalidade e desempenho!
Função           class Trem(object):
                     def __init__(self, num_vagoes):

geradora                 self.num_vagoes = num_vagoes
                     def __iter__(self):
                         for i in range(self.num_vagoes):
                             yield 'vagao #%s' % (i+1)
 3 linhas
Expressão
geradora             >>> g = (n for n in [1, 2, 3])
                     >>> for i in g: print i
                     ...
                     1
                     2
                     3

• Quando avaliada,   >>> g = (n for n in [1, 2, 3])
                     >>> g
  devolve um         <generator object <genexpr> at
                     0x109a4deb0>
  objeto gerador     >>> g.next()
                     1

• O objeto gerador   >>> g.next()
                     2
  é um iterável      >>> g.next()
                     3
                     >>> g.next()
                     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
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
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
Oficinas Turing:
    computação para programadores

•   Próximos lançamentos:

    •   4ª turma de Python para quem sabe Python

    •   3ª turma de Objetos Pythonicos

    •   1ª turma de Aprenda Python com um Pythonista



        Turing.com.br

Weitere ähnliche Inhalte

Was ist angesagt?

Polymorphism in C++
Polymorphism in C++Polymorphism in C++
Polymorphism in C++Rabin BK
 
PYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYA
PYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYAPYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYA
PYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYAMaulik Borsaniya
 
Templates in C++
Templates in C++Templates in C++
Templates in C++Tech_MX
 
Unit II chapter 4 Loops in C
Unit II chapter 4 Loops in CUnit II chapter 4 Loops in C
Unit II chapter 4 Loops in CSowmya Jyothi
 
Object oriented programming with python
Object oriented programming with pythonObject oriented programming with python
Object oriented programming with pythonArslan Arshad
 
Arrays (vetores) em Java
Arrays (vetores) em JavaArrays (vetores) em Java
Arrays (vetores) em JavaDaniel Brandão
 
Let’s Learn Python An introduction to Python
Let’s Learn Python An introduction to Python Let’s Learn Python An introduction to Python
Let’s Learn Python An introduction to Python Jaganadh Gopinadhan
 
Introduction to the basics of Python programming (part 1)
Introduction to the basics of Python programming (part 1)Introduction to the basics of Python programming (part 1)
Introduction to the basics of Python programming (part 1)Pedro Rodrigues
 
Exception handling c++
Exception handling c++Exception handling c++
Exception handling c++Jayant Dalvi
 
Programação Orientada a Objetos
Programação Orientada a ObjetosProgramação Orientada a Objetos
Programação Orientada a ObjetosIgor Takenami
 
Managing console input and output
Managing console input and outputManaging console input and output
Managing console input and outputgourav kottawar
 
Python Programming: Lists, Modules, Exceptions
Python Programming: Lists, Modules, ExceptionsPython Programming: Lists, Modules, Exceptions
Python Programming: Lists, Modules, ExceptionsSreedhar Chowdam
 

Was ist angesagt? (20)

Polymorphism in C++
Polymorphism in C++Polymorphism in C++
Polymorphism in C++
 
PYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYA
PYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYAPYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYA
PYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYA
 
Templates in C++
Templates in C++Templates in C++
Templates in C++
 
Unit II chapter 4 Loops in C
Unit II chapter 4 Loops in CUnit II chapter 4 Loops in C
Unit II chapter 4 Loops in C
 
Object oriented programming with python
Object oriented programming with pythonObject oriented programming with python
Object oriented programming with python
 
Arrays (vetores) em Java
Arrays (vetores) em JavaArrays (vetores) em Java
Arrays (vetores) em Java
 
Let’s Learn Python An introduction to Python
Let’s Learn Python An introduction to Python Let’s Learn Python An introduction to Python
Let’s Learn Python An introduction to Python
 
Introduction to the basics of Python programming (part 1)
Introduction to the basics of Python programming (part 1)Introduction to the basics of Python programming (part 1)
Introduction to the basics of Python programming (part 1)
 
Control statements
Control statementsControl statements
Control statements
 
JAVA - Orientação a Objetos
JAVA - Orientação a ObjetosJAVA - Orientação a Objetos
JAVA - Orientação a Objetos
 
Exception handling c++
Exception handling c++Exception handling c++
Exception handling c++
 
Programação Orientada a Objetos
Programação Orientada a ObjetosProgramação Orientada a Objetos
Programação Orientada a Objetos
 
Java Docs
Java DocsJava Docs
Java Docs
 
Managing console input and output
Managing console input and outputManaging console input and output
Managing console input and output
 
Python Programming
Python ProgrammingPython Programming
Python Programming
 
C++ programming
C++ programmingC++ programming
C++ programming
 
Classes e Objectos JAVA
Classes e Objectos JAVAClasses e Objectos JAVA
Classes e Objectos JAVA
 
Java String class
Java String classJava String class
Java String class
 
Python Programming: Lists, Modules, Exceptions
Python Programming: Lists, Modules, ExceptionsPython Programming: Lists, Modules, Exceptions
Python Programming: Lists, Modules, Exceptions
 
Python OOPs
Python OOPsPython OOPs
Python OOPs
 

Andere mochten auch

Iteráveis e geradores (versão RuPy)
Iteráveis e geradores (versão RuPy)Iteráveis e geradores (versão RuPy)
Iteráveis e geradores (versão RuPy)Luciano Ramalho
 
Apresentação Python Poli
Apresentação Python PoliApresentação Python Poli
Apresentação Python PoliRodrigo Lira
 
Introdução a Python - Python Poli
Introdução a Python  - Python PoliIntrodução a Python  - Python Poli
Introdução a Python - Python PoliRodrigo Lira
 
Introdução a linguagem Python
Introdução a linguagem PythonIntrodução a linguagem Python
Introdução a linguagem PythonLuciano Ramalho
 
Desvendando o python
Desvendando o pythonDesvendando o python
Desvendando o pythonRodrigo Lira
 

Andere mochten auch (11)

Modelos ricos
Modelos ricosModelos ricos
Modelos ricos
 
Iteráveis e geradores (versão RuPy)
Iteráveis e geradores (versão RuPy)Iteráveis e geradores (versão RuPy)
Iteráveis e geradores (versão RuPy)
 
Mongodb: agregação
Mongodb: agregaçãoMongodb: agregação
Mongodb: agregação
 
Sokoban com PyS60
Sokoban com PyS60Sokoban com PyS60
Sokoban com PyS60
 
Apresentação Python Poli
Apresentação Python PoliApresentação Python Poli
Apresentação Python Poli
 
Python Poli 2010
Python Poli 2010Python Poli 2010
Python Poli 2010
 
Wiki-wiki S/A
Wiki-wiki S/AWiki-wiki S/A
Wiki-wiki S/A
 
Introdução a Python - Python Poli
Introdução a Python  - Python PoliIntrodução a Python  - Python Poli
Introdução a Python - Python Poli
 
Introdução a linguagem Python
Introdução a linguagem PythonIntrodução a linguagem Python
Introdução a linguagem Python
 
Desvendando o python
Desvendando o pythonDesvendando o python
Desvendando o python
 
REST com Python
REST com PythonREST com Python
REST com Python
 

Ähnlich wie Objetos Pythonicos - compacto

Iteraveis e geradores em Python
Iteraveis e geradores em PythonIteraveis e geradores em Python
Iteraveis e geradores em PythonLuciano Ramalho
 
Python: Iteraveis, geradores etc
Python: Iteraveis, geradores etcPython: Iteraveis, geradores etc
Python: Iteraveis, geradores etcLuciano Ramalho
 
Python para quem sabe Python (aula 2)
Python para quem sabe Python (aula 2)Python para quem sabe Python (aula 2)
Python para quem sabe Python (aula 2)Luciano Ramalho
 
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
 
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
 
Introdução à Programação em Python
Introdução à Programação em PythonIntrodução à Programação em Python
Introdução à Programação em PythonRodrigo Hübner
 
Jython no JavaOne Latin America 2011
Jython no JavaOne Latin America 2011Jython no JavaOne Latin America 2011
Jython no JavaOne Latin America 2011Luciano Ramalho
 
Desenvolvendo com mongodb
Desenvolvendo com mongodbDesenvolvendo com mongodb
Desenvolvendo com mongodbThiago Avelino
 
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
 
Introdução a JavaScript
Introdução a JavaScriptIntrodução a JavaScript
Introdução a JavaScriptBruno Catão
 
As Novidades Do C# 4.0 - NetPonto
As Novidades Do C# 4.0 - NetPontoAs Novidades Do C# 4.0 - NetPonto
As Novidades Do C# 4.0 - NetPontoPaulo Morgado
 
Programação Web com PHP 7.x
Programação Web com PHP 7.xProgramação Web com PHP 7.x
Programação Web com PHP 7.xNorton Guimarães
 
Criando sua própria linguagem de programação
Criando sua própria linguagem de programaçãoCriando sua própria linguagem de programação
Criando sua própria linguagem de programaçãoronaldoferraz
 
Scala: unindo programação funcional e orientação a objetos
Scala: unindo programação funcional e orientação a objetosScala: unindo programação funcional e orientação a objetos
Scala: unindo programação funcional e orientação a objetosFelipe Hummel
 

Ähnlich wie Objetos Pythonicos - compacto (20)

Iteraveis e geradores em Python
Iteraveis e geradores em PythonIteraveis e geradores em Python
Iteraveis e geradores em Python
 
Python: Iteraveis, geradores etc
Python: Iteraveis, geradores etcPython: Iteraveis, geradores etc
Python: Iteraveis, geradores etc
 
Python para quem sabe Python (aula 2)
Python para quem sabe Python (aula 2)Python para quem sabe Python (aula 2)
Python para quem sabe Python (aula 2)
 
Python
PythonPython
Python
 
Iteraveis e geradores
Iteraveis e geradoresIteraveis e geradores
Iteraveis e geradores
 
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
 
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?
 
Introdução à Programação em Python
Introdução à Programação em PythonIntrodução à Programação em Python
Introdução à Programação em Python
 
Jython no JavaOne Latin America 2011
Jython no JavaOne Latin America 2011Jython no JavaOne Latin America 2011
Jython no JavaOne Latin America 2011
 
Python2.5.ppt
Python2.5.pptPython2.5.ppt
Python2.5.ppt
 
Aula python
Aula pythonAula python
Aula python
 
Desenvolvendo com mongodb
Desenvolvendo com mongodbDesenvolvendo com mongodb
Desenvolvendo com mongodb
 
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
 
Introdução a JavaScript
Introdução a JavaScriptIntrodução a JavaScript
Introdução a JavaScript
 
As Novidades Do C# 4.0 - NetPonto
As Novidades Do C# 4.0 - NetPontoAs Novidades Do C# 4.0 - NetPonto
As Novidades Do C# 4.0 - NetPonto
 
Programação Web com PHP 7.x
Programação Web com PHP 7.xProgramação Web com PHP 7.x
Programação Web com PHP 7.x
 
Criando sua própria linguagem de programação
Criando sua própria linguagem de programaçãoCriando sua própria linguagem de programação
Criando sua própria linguagem de programação
 
Monadic Design
Monadic DesignMonadic Design
Monadic Design
 
Haskell
HaskellHaskell
Haskell
 
Scala: unindo programação funcional e orientação a objetos
Scala: unindo programação funcional e orientação a objetosScala: unindo programação funcional e orientação a objetos
Scala: unindo programação funcional e orientação a objetos
 

Mehr von 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
 
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
 

Mehr von Luciano Ramalho (18)

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
 
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
 
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
 
Trilha python
Trilha pythonTrilha python
Trilha python
 

Objetos Pythonicos - compacto

  • 1. Luciano Ramalho luciano@ramalho.org outubro/2012 ac to mp Objetos Pythonicos co Orientação a objetos e padrões de projeto em Python
  • 2. Conceito: “objeto” • Um componente de software que inclui dados (campos) e comportamentos (métodos) • Em geral, os atributos são manipulados pelos métodos do próprio objeto (encapsulamento) Figuras: bycicle (bicicleta), The Java Tutorial http://docs.oracle.com/javase/tutorial/java/concepts/object.html
  • 3. Terminologia pythonica • Objetos possuem atributos • Os atributos de um objeto podem ser: • métodos funções associadas • atributos de dados “campos” Figuras: bycicle (bicicleta), The Java Tutorial http://docs.oracle.com/javase/tutorial/java/concepts/object.html
  • 4. Exemplo: um objeto dict >>> d = {'AM':'Manaus', 'PE':'Recife', 'PR': 'Curitiba'} >>> d.keys() ['PR', 'AM', 'PE'] >>> d.get('PE') 'Recife' >>> d.pop('PR') 'Curitiba' >>> d {'AM': 'Manaus', 'PE': 'Recife'} >>> len(d) 2 >>> d.__len__() 2 • Métodos: keys, get, pop, __len__ etc.
  • 5. Exemplo: um objeto dict • dir revela atributos de um dict • atributos de dados e métodos >>> dir(d) ['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
  • 6. Exemplo: um objeto dict • Sobrecarga de operadores: • [ ]: __getitem__, __setitem__ >>> d {'AM': 'Manaus', 'PE': 'Recife'} >>> d['AM'] 'Manaus' >>> d.__getitem__('AM') 'Manaus' >>> d['MG'] = 'Belo Horizonte' >>> d.__setitem__('RJ', 'Rio de Janeiro') >>> d {'MG': 'Belo Horizonte', 'AM': 'Manaus', 'RJ': 'Rio de Janeiro', 'PE': 'Recife'}
  • 7. Exemplo: um objeto dict • Atributos de dados: __class__, __doc__ >>> d.__class__ <type 'dict'> >>> type(d) <type 'dict'> >>> print d.__doc__ dict() -> new empty dictionary. dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs. dict(seq) -> new dictionary initialized as if via: d = {} for k, v in seq: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)
  • 8. Exemplo: outro dict >>> d = dict() >>> d.keys() [] • d = dict() >>> d.get('bla') >>> print d.get('bla') é o mesmo que None d = {} >>> d.get('spam') >>> print d.get('spam') None >>> d.pop('ovos') Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'ovos' >>> d {} >>> len(d) 0 >>> d.__len__() 0
  • 9. Exercício: construir e controlar Tkinter.Label import Tkinter relogio = Tkinter.Label() relogio.pack() relogio['font'] = 'Helvetica 120 bold' relogio['text'] = strftime('%H:%M:%S') from time import strftime def tic():     relogio['text'] = strftime('%H:%M:%S')      def tac(): Note: no Tkinter, atributos     relogio.after(100, tictac) de dados são acessados via [ ]: tac() relogio.mainloop() __getitem__ __setitem__
  • 10. Tudo é um objeto • Não existem “tipos primitivos” como em Java • desde Python 2.2, dezembro de 2001 >>> 5 + 3 8 >>> 5 .__add__(3) 8 >>> type(5) <type 'int'>
  • 11. Tipos embutidos • Implementados em C, por eficiência • Comportamentos fixos • Texto: str, unicode • Números: int, long, float, complex, bool • Coleções: list, tuple, dict, set, frozenset • etc.
  • 12. Funções são objetos >>> def fatorial(n): ... '''devolve n!''' ... return 1 if n < 2 else n * fatorial(n-1) ... >>> fatorial(5) 120 >>> fat = fatorial >>> fat <function fatorial at 0x1004b5f50> >>> fat(42) 1405006117752879898543142606244511569936384000000000L >>> fatorial.__doc__ 'devolve n!' >>> fatorial.__name__ 'fatorial' >>> fatorial.__code__ <code object fatorial at 0x1004b84e0, file "<stdin>", line 1> >>> fatorial.__code__.co_varnames ('n',)
  • 13. Funções são objetos >>> fatorial.__code__.co_code '|x00x00dx01x00jx00x00ox05x00x01dx02x00Sx01|x00x00tx00x00| x00x00dx02x00x18x83x01x00x14S' >>> from dis import dis >>> dis(fatorial.__code__.co_code) 0 LOAD_FAST 0 (0) 3 LOAD_CONST 1 (1) 6 COMPARE_OP 0 (<) Bytecode da 9 JUMP_IF_FALSE 5 (to 17) 12 POP_TOP 13 LOAD_CONST 2 (2) >> 16 RETURN_VALUE 17 POP_TOP função fatorial 18 LOAD_FAST 0 (0) 21 LOAD_GLOBAL 0 (0) 24 LOAD_FAST 0 (0) 27 LOAD_CONST 2 (2) 30 BINARY_SUBTRACT 31 CALL_FUNCTION 1 34 BINARY_MULTIPLY 35 RETURN_VALUE >>>
  • 14. Tipagem forte • O tipo de um objeto nunca muda • Raramente Python faz conversão automática de tipos >>> a = 10 >>> b = '9' >>> a + b Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for +: 'int' and 'str' >>> a + int(b) 19 >>> str(a) + b '109' >>> 77 * None Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for *: 'int' and 'NoneType' >>>
  • 15. Tipagem dinâmica: variáveis não têm tipo >>> def dobro(x): ... return x * 2 ... >>> dobro(7) 14 >>> dobro(7.1) 14.2 >>> dobro('bom') 'bombom' >>> dobro([10, 20, 30]) [10, 20, 30, 10, 20, 30] >>> dobro(None) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in dobro TypeError: unsupported operand type(s) for *: 'NoneType' and 'int'
  • 16. Orientação a objetos: a origem • Linguagem Simula 1967 • Noruega: Ole-Johan Dahl e Kristen Nygaard • objetos, classes, sub-classes • métodos virtuais (funções associadas a objetos específicos somente em tempo de execução, e não na compilação)
  • 17. Orientação a objetos: evolução • Smalltalk 1980 • EUA, Xerox PARC (Palo Alto Research Center): Alan Kay, Dan Ingalls, Adele Goldberg et. al. • Terminologia: • “Object oriented programming” • “message passing” (invocação de métodos), “late binding” (métodos virtuais)
  • 20. Duck typing • “Se voa como um pato, nada como um pato e grasna como um pato, é um pato.” • Tipagem dinâmica permite duck typing (tipagem pato) estilo de programação que evita verificar os tipos dos objetos, mas apenas seus métodos • No exemplo anterior, a função dobro funciona com qualquer objeto x que consiga fazer x * 2 • x implementa o método __mult__(n), para n inteiro
  • 21. Tipagem forte x fraca JavaScript (ECMAScript 5) • Tipagem forte x fraca refere-se a em Node.js 0.6 conversão automática de valores de tipos diferente. • Linguagens de tipagem fraca são muito > 10 + '9' '109' > 10 + '9' * 1 liberais na mistura entre tipos, e isso é 19 uma fonte de bugs. > '10' + 9 * 1 '109' Veja alguns resultados estranhos obtidos > 0 == '0' com JavaScript, que tem tipagem fraca. true > 0 == '' Em Python as três expressões acima geram true TypeError, e as três últimas resultam False. > '0' == '' Python tem tipagem forte. false
  • 22. Tipagem forte x fraca, dinâmica x estática • Tipagem forte x fraca refere-se a conversão automática de valores de tipos diferentes • Tipagem dinâmica x estática refere-se à declaração dos tipos das variáveis, parâmetros formais e valores devolvidos pelas funções • Linguagens de tipagem estática exigem a declaração dos tipos, ou usam inferência de tipos para garantir que uma variável será associada a somente a valores de um tipo
  • 23. Tipagem em linguagens Smalltalk dinâmica forte Python dinâmica forte Ruby dinâmica forte C (K&R) estática fraca C (ANSI) estática forte Java estática forte C# estática forte combinação JavaScript PHP dinâmica dinâmica fraca fraca } perigosa: bugs sorrateiros
  • 24. Conversões automáticas • Python faz algumas (poucas) conversões automáticas entre tipos: • Promoção de int para float • Promoção de str para unicode • assume o encoding padrão: ASCII por default >>> 6 * 7.0 42.0 >>> 'Spam, ' + u'eggs' u'Spam, eggs' >>>
  • 25. Tipos são classes • Para criar um novo tipo de objeto, crie uma classe • A função type devolve a classe de um objeto >>> class Mamifero(object): ... pass ... >>> kingkong = Mamifero() >>> type(kingkong) <class '__main__.Mamifero'> >>> ClasseDoKingKong = type(kingkong) >>> dumbo = ClasseDoKingKong() >>> dumbo <__main__.Mamifero object at 0x10045dcd0> >>> type(dumbo) <class '__main__.Mamifero'>
  • 26. Conceito: “classe” • Uma categoria, ou tipo, de objeto • Uma idéia abstrata, uma forma platônica • Exemplo: classe “Cão”: • Eu digo: “Ontem eu comprei um cão” • Você não sabe exatamente qual cão, mas sabe: • é um mamífero, quadrúpede, carnívoro • pode ser domesticado (normalmente) • cabe em um automóvel
  • 27. Exemplar de cão: instância da classe Cao >>> rex = Cao() instanciação
  • 28. instanciação >>> rex = Cao('Rex') >>> rex Classe Cao Cao('Rex') >>> print rex Rex >>> rex.qt_patas class Mamifero(object): 4     """lição de casa: implementar""" >>> rex.latir() Rex: Au! class Cao(Mamifero): >>> rex.latir(2)     qt_patas = 4     carnivoro = True Rex: Au! Au!     nervoso = False >>> rex.nervoso = True     def __init__(self, nome): >>> rex.latir(3)         self.nome = nome Rex: Au! Au! Au! Au! Au! Au!     def latir(self, vezes=1):         # quando nervoso, late o dobro         vezes = vezes + (self.nervoso * vezes)         print self.nome + ':' + ' Au!' * vezes     def __str__(self):         return self.nome     def __repr__(self):         return 'Cao({0!r})'.format(self.nome) oopy/exemplos/cao.py
  • 29. Como atributos são acessados • Ao buscar o.a (atributo a do objeto o da classe C), o interpretador Python faz o seguinte: • 1) acessa atributo a da instancia o; caso não exista... • 2) acessa atributo a da classe C de o (type(o) ou o.__class__); caso nao exista... • 3) busca o atributo a nas superclasses de C, conforme a MRO (method resolution order)
  • 30. Classe Cao em Python class Mamifero(object):     """lição de casa: implementar""" • __init__ é o class Cao(Mamifero):     qt_patas = 4 construtor, ou melhor,     carnivoro = True     nervoso = False o inicializador •     def __init__(self, nome):         self.nome = nome     def latir(self, vezes=1): self é o 1º parâmetro         # quando nervoso, late o dobro formal em todos os         vezes = vezes + (self.nervoso * vezes)         print self.nome + ':' + ' Au!' * vezes métodos de instância     def __str__(self):         return self.nome     def __repr__(self):         return 'Cao({0!r})'.format(self.nome) oopy/exemplos/cao.py
  • 31. >>> rex = Cao('Rex') >>> rex Classe Cao Cao('Rex') >>> print rex Rex >>> rex.qt_patas class Mamifero(object): 4     """lição de casa: implementar""" >>> rex.latir() Rex: Au! class Cao(Mamifero): invocação >>> rex.latir(2)     qt_patas = 4 Rex: Au! Au!     carnivoro = True     nervoso = False •     def __init__(self, nome):         self.nome = nome     def latir(self, vezes=1): na invocação do         # quando nervoso, late o dobro método, a instância         vezes = vezes + (self.nervoso * vezes)         print self.nome + ':' + ' Au!' * vezes é passada     def __str__(self):         return self.nome automaticamente     def __repr__(self):         return 'Cao({0!r})'.format(self.nome) na posição do self oopy/exemplos/cao.py
  • 32. Classe Cao em Python class Mamifero(object):     """lição de casa: implementar""" • atributos de dados na classe funcionam class Cao(Mamifero):     qt_patas = 4 como valores default     carnivoro = True     nervoso = False para os atributos das     def __init__(self, nome):         self.nome = nome instâncas •     def latir(self, vezes=1):         # quando nervoso, late o dobro         vezes = vezes + (self.nervoso * vezes) atributos da instância         print self.nome + ':' + ' Au!' * vezes só podem ser     def __str__(self):         return self.nome acessados via self     def __repr__(self):         return 'Cao({0!r})'.format(self.nome) oopy/exemplos/cao.py
  • 33. Mamifero: superclasse de Cao class Mamifero(object): UML diagrama de classe     """lição de casa: implementar""" especialização class Cao(Mamifero): generalização     qt_patas = 4     carnivoro = True     nervoso = False     def __init__(self, nome):         self.nome = nome     def latir(self, vezes=1):         # quando nervoso, late o dobro         vezes = vezes + (self.nervoso * vezes)         print self.nome + ':' + ' Au!' * vezes     def __str__(self):         return self.nome     def __repr__(self):         return 'Cao({0!r})'.format(self.nome) oopy/exemplos/cao.py
  • 34. Subclasses de Cao • Continuação de cao.py class Pequines(Cao):     nervoso = True      class Mastiff(Cao):     def latir(self, vezes=1):         # o mastiff não muda seu latido quando nervoso         print self.nome + ':' + ' Wuff!' * vezes          class SaoBernardo(Cao):     def __init__(self, nome):         Cao.__init__(self, nome)         self.doses = 10 Diz a lenda que o cão     def servir(self): São Bernardo leva um         if self.doses == 0: pequeno barril de conhaque             raise ValueError('Acabou o conhaque!')         self.doses -= 1 para resgatar viajantes         msg = '{0} serve o conhaque (restam {1} doses)' perdidos na neve.         print msg.format(self.nome, self.doses)
  • 35. Subclasses >>> sansao = SaoBernardo('Sansao') de Cao >>> sansao.servir() Sansao serve o conhaque (restam 9 doses) >>> sansao.doses = 1 >>> sansao.servir() Sansao serve o conhaque (restam 0 doses) >>> sansao.servir() class Pequines(Cao): Traceback (most recent call last):     nervoso = True ...      class Mastiff(Cao): ValueError: Acabou o conhaque!     def latir(self, vezes=1):         # o mastiff não muda seu latido quando nervoso         print self.nome + ':' + ' Wuff!' * vezes          class SaoBernardo(Cao):     def __init__(self, nome):         Cao.__init__(self, nome)         self.doses = 10     def servir(self):         if self.doses == 0:             raise ValueError('Acabou o conhaque!')         self.doses -= 1         msg = '{0} serve o conhaque (restam {1} doses)'         print msg.format(self.nome, self.doses)
  • 36. Subclasses de Cao • Continuação de cao.py class Pequines(Cao):     nervoso = True      class Mastiff(Cao):     def latir(self, vezes=1):         # o mastiff não muda seu latido quando nervoso         print self.nome + ':' + ' Wuff!' * vezes          class SaoBernardo(Cao):     def __init__(self, nome):         Cao.__init__(self, nome)         self.doses = 10     def servir(self):         if self.doses == 0:             raise ValueError('Acabou o conhaque!')         self.doses -= 1         msg = '{0} serve o conhaque (restam {1} doses)'         print msg.format(self.nome, self.doses)
  • 37. Interface • Interface é um conceito essencial em OO • não depende de uma palavra reservada A interface fornece uma separação entre a implementação de uma abstração e seus clientes. Ela limita os detalhes de implementação que os clientes podem ver. Também especifica a funcionalidade que as implementações devem prover. P. S. Canning, W. R. Cook, W. L. Hill, and W. G. Olthoff. 1989. Interfaces for strongly-typed object- oriented programming. In Conference proceedings on Object-oriented programming systems, languages and applications (OOPSLA '89). ACM, New York, NY, USA, 457-467. DOI=10.1145/74877.74924 http://doi.acm.org/10.1145/74877.74924
  • 38. Interfaces e protocolos • Em SmallTalk, as interfaces eram chamadas de “protocolos”. • Não há verificação de interfaces na linguagem, mas algumas IDEs (“browsers”) permitem agrupar os métodos por protocolo para facilitar a leitura • Um protocolo é uma interface informal, não declarada porém implementada por métodos concretos
  • 39. Interfaces em Python • Conceitualmente, sempre existiram como protocolos • Não havia maneira formal de especificar interfaces em Python até a versão 2.5 • usava-se termos como “uma sequência” ou “a file-like object” • Agora temos ABC (Abstract Base Class) • com herança múltipla, como em C++
  • 40. Exemplo: tômbola • Sortear um a um todos os itens de uma coleção finita, sem repetir • A mesma lógica é usada em sistemas para gerenciar banners online
  • 41. Interface da tômbola • Carregar itens • Misturar itens • Sortear um item • Indicar se há mais itens
  • 42. Projeto da tômbola • UML: diagrama de classe
  • 43. TDD: Test Driven Design • Metodologia de desenvolvimento iterativa na qual, para cada funcionalidade nova, um teste é criado antes do código a ser implementado • Esta inversão ajuda o programador a desenvolver com disciplina apenas uma funcionalidade de cada vez, mantendo o foco no teste que precisa passar • Cada iteração de teste/implementação deve ser pequena e simples: “baby steps” (passinhos de bebê)
  • 44. Doctests • Um dos módulos para fazer testes automatizados na biblioteca padrão de Python • o outro módulo é o unittest, da família xUnit • Doctests foram criados para testar exemplos embutidos na documentação • Usaremos doctests para especificar exercícios • Exemplo: $ python -m doctest cao.rst oopy/exemplos/cao.rst
  • 45. Coding Dojo • Implementação da classe Tombola, com testes feitos em Doctest
  • 46. Implementação da tômbola # coding: utf-8 import random class Tombola(object): itens = None def carregar(self, itens): self.itens = list(itens) def carregada(self): return bool(self.itens) def misturar(self): • Python 2.2 a 2.7 random.shuffle(self.itens) def sortear(self): return self.itens.pop()
  • 47. Iteração em 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
  • 48. 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
  • 49. ano: Iteração em Java ≥1.5 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
  • 50. ano: Iteração em Java ≥1.5 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
  • 51. Exemplos de iteração • Iteração em Python não se limita a tipos primitivos • Exemplos • string • arquivo • Django QuerySet • Baralho (em: “OO em Python sem Sotaque”) https://slideshare.net/ramalho/ @ramalhoorg
  • 52. 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] @ramalhoorg
  • 53. 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
  • 54. 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
  • 55. Tipos iteráveis embutidos • basestring • frozenset • str • list • unicode • set • dict • tuple • file • xrange @ramalhoorg
  • 56. Funções embutidas que consomem iteráveis • all • max • any • min • filter • reduce • iter • sorted • len • sum • map • zip @ramalhoorg
  • 57. 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
  • 58. 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 fazendo x[0], x[1], x[2] etc. @ramalhoorg
  • 59. Protocolo de sequência >>> t = Trem(4) >>> len(t) 4 __len__ >>> t[0] 'vagao #1' >>> t[3] __getitem__ 'vagao #4' >>> t[-1] 'vagao #4' >>> for vagao in t: ... print(vagao) __getitem__ vagao #1 vagao #2 vagao #3 vagao #4 @ramalhoorg
  • 60. Protocolo de sequência • implementação “informal” da interface class Trem(object): def __init__(self, num_vagoes): self.num_vagoes = num_vagoes def __len__(self): return self.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: @ramalhoorg raise IndexError('vagao inexistente %s' % pos)
  • 61. Tômbola como sequência • Permitir contagem de itens • Permitir acesso direto a cada item pela ordem em que foi colocado Sim, este é um exemplo forçado... mas daqui a pouco melhora!
  • 62. Interface Sequence • collections.Sequence from collections import Sequence class Trem(Sequence): def __init__(self, num_vagoes): self.num_vagoes = num_vagoes def __len__(self): return self.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: @ramalhoorg raise IndexError('vagao inexistente %s' % pos)
  • 63. 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 vagao #3 from collections import Seque vagao #2 vagao #1 class Trem(Sequence): >>> t.index('vagao #2') def __init__(self, num_va 1 self.num_vagoes = num >>> t.index('vagao #7') def __len__(self): Traceback (most recent call last): return self.num_vagoe ... def __getitem__(self, pos ValueError @ramalhoorg indice = pos if pos >
  • 64. Interface Iterable • Iterable provê um método __iter__ • O método __iter__ devolve uma instância de Iterator @ramalhoorg
  • 65. Iterator é... • um padrão de projeto Design Patterns Gamma, Helm, Johnson & Vlissides Addison-Wesley, ISBN 0-201-63361-2 @ramalhoorg
  • 67. 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
  • 68. Trem class Trem(object): def __init__(self, num_vagoes): self.num_vagoes = num_vagoes def __iter__(self): com return IteradorTrem(self.num_vagoes) class IteradorTrem(object): iterator def __init__(self, num_vagoes): self.atual = 0 self.ultimo_vagao = num_vagoes - 1 def next(self): if self.atual <= self.ultimo_vagao: self.atual += 1 return 'vagao #%s' % (self.atual) else: iter(t) 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 itrem.next() até que vagao #4 ele levante StopIteration @ramalhoorg
  • 69. Tômbola iterável • Permitir iteração sobre tômbola em um laço for, devolvendo os itens em uma ordem sorteada Agora o exemplo faz mais sentido!
  • 70. Recapitulando: 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 fazendo x[0], x[1], x[2] etc. protocolo de sequência @ramalhoorg
  • 71. 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
  • 72. Iteração em 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 @ramalhoorg
  • 73. 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
  • 74. Função >>> def g123(): geradora ... yield 1 ... yield 2 ... yield 3 ... >>> for i in g123(): print i ... • Quando invocada, 1 2 3 devolve um >>> g = g123() >>> g objeto gerador <generator object g123 at 0x10e385e10> • O objeto gerador >>> g.next() 1 >>> g.next() é um iterável 2 >>> g.next() 3 >>> g.next() Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration @ramalhoorg
  • 75. Trem c/ função geradora class Trem(object): def __init__(self, num_vagoes): self.num_vagoes = num_vagoes def __iter__(self): for i in range(self.num_vagoes): yield 'vagao #%s' % (i+1) 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
  • 76. class Trem(object): Iterador def __init__(self, num_vagoes): self.num_vagoes = num_vagoes def __iter__(self): clássico return IteradorTrem(self.num_vagoes) class IteradorTrem(object): def __init__(self, num_vagoes): 12 linhas self.atual = 0 self.ultimo_vagao = num_vagoes - 1 de código def next(self): if self.atual <= self.ultimo_vagao: self.atual += 1 return 'vagao #%s' % (self.atual) else: raise StopIteration() mesma funcionalidade e desempenho! Função class Trem(object): def __init__(self, num_vagoes): geradora self.num_vagoes = num_vagoes def __iter__(self): for i in range(self.num_vagoes): yield 'vagao #%s' % (i+1) 3 linhas
  • 77. Expressão geradora >>> g = (n for n in [1, 2, 3]) >>> for i in g: print i ... 1 2 3 • Quando avaliada, >>> g = (n for n in [1, 2, 3]) >>> g devolve um <generator object <genexpr> at 0x109a4deb0> objeto gerador >>> g.next() 1 • O objeto gerador >>> g.next() 2 é um iterável >>> g.next() 3 >>> g.next() Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration @ramalhoorg
  • 78. 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
  • 79. Construtores embutidos que consomem e produzem iteráveis • dict • reversed • enumerate • set • frozenset • tuple • list @ramalhoorg
  • 80. 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
  • 81. 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
  • 83. Um outro laço lê os registros a converter @ramalhoorg
  • 84. Implementação possível: o mesmo laço lê e grava @ramalhoorg
  • 85. Mas e a lógica para ler outro formato? @ramalhoorg
  • 86. Funções do script • iterMstRecords* • iterIsoRecords* • writeJsonArray • main * funções geradoras @ramalhoorg
  • 88. 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
  • 90. writeJsonArray: itera sobre umas das funções geradoras @ramalhoorg
  • 91. iterIsoRecords: ler registros função geradora! de arquivo ISO-2709 @ramalhoorg
  • 92. iterIsoRecords cria um novo dict a cada iteração produz (yield) registro na forma de um dict @ramalhoorg
  • 93. iterMstRecords: função geradora! ler registros de arquivo ISIS .MST @ramalhoorg
  • 94. iterMstRecords iterIsoRecords cria um novo dict a cada iteração produz (yield) registro na forma de um dict @ramalhoorg
  • 95. Geradores na prática @ramalhoorg
  • 96. Geradores na prática @ramalhoorg
  • 97. Geradores na prática @ramalhoorg
  • 98. Oficinas Turing: computação para programadores • Próximos lançamentos: • 4ª turma de Python para quem sabe Python • 3ª turma de Objetos Pythonicos • 1ª turma de Aprenda Python com um Pythonista Turing.com.br