SlideShare uma empresa Scribd logo
1 de 107
Baixar para ler offline
Luciano Ramalho
  luciano@ramalho.org




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


• Em geral, os campos 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 vinculadas

 • 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
rel = Tkinter.Label()
rel['text'] = '10:42:29'
rel.grid()
rel['font'] = 'Helvetica 120 bold'

from time import strftime
rel['text'] = strftime('%H:%M:%S')

def tic():
    rel['text'] = strftime('%H:%M:%S')
                                              Para instalar
def tac():
     tic()
                                               Tkinter no
    rel.after(100, tac)                       Ubuntu Linux:

tac()                     $ sudo apt-get install python-tk
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'>
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
>>>
Tipos
Alguns tipos básicos
>>> i = 7          Python 2.7            >>> i = 7       Python 3.2
>>> type(i)                              >>> type(i)
<type 'int'>                             <class 'int'>
>>> j = 2**100                           >>> j = 2**100
>>> type(j)
                           int e long    >>> type(j)
<type 'long'>            unificados no   <class 'int'>
>>> f = 7.                 Python 3      >>> f = 7.
>>> type(f)                              >>> type(f)
<type 'float'>                           <class 'float'>
>>> s = 'abc'                            >>> s = 'abc'
>>> type(s)                   str        >>> type(s)
<type 'str'>                   x         <class 'str'>    SyntaxError
>>> u = u'abc'              unicode      >>> u = u'abc'
                                                                ou
>>> type(u)                    x
<type 'unicode'>                                           <class ‘s tr’>
                             bytes
>>> b = b'ABC'                           >>> b = b'ABC'    (Python 3.3)
>>> type(b)                              >>> type(b)
<type 'str'>                             <class 'bytes'>
>>> b[0]                                 >>> b[0]
'A'                                      65
Tipos embutidos (built-in)
• Implementados em C, por eficiência
• Métodos inalteráveis (como “final”, em Java)
• Texto: str, unicode (Python 2 e Python 3)
• Números: int, long (Python 2), float, complex, bool
• Coleções: list, tuple, dict, set, frozenset, bytes
  (Python 3)
• etc.
Tipagem forte
• O tipo de um objeto nunca muda, e não existem
  “tipos variantes”
• Raramente Python faz conversão automática
    >>> 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'
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
Mutabilidade
• Em Python, alguns objetos são mutáveis, outros são
  imutáveis
• Objetos mutáveis possuem conteúdo ou estado
  interno (atributos de dados) que podem ser
  alterados ao longo da sua existência
• Objetos imutáveis não podem alterados de
  nenhuma maneira. Seu estado é congelado no
  momento da inicialização.
Mutabilidade: exemplos
   Mutáveis                   Imutáveis

• list                     • tuple
• dict                     • str, unicode, bytes
• set                      • frozenset
• objetos que permitem a   • int, float, complex
  alteração de atributos
  por acesso direto,
  setters ou outros
  métodos
Variáveis e
referências
Variáveis não são “caixas”!
• Abandone essa idéia!
 • Ela é válida em C e Pascal, mas
    não em Python ou Java
• Variáveis são rótulos (ou post-its)
  que identificam objetos
• O objeto identificado já existe
  quando o rótulo é atribuído
Objetos e variáveis
• Objetos existem antes das variáveis
• Em uma atribuição, o lado direito do = é
    executado primeiro. Prova:
Primeiro o objeto     >>> x = 10
                      >>> x
   10 é criado,       10
depois a variável     >>> y = 7 / 0
a é atribuída a ele   Traceback (most recent call last):
                         File "<stdin>", line 1, in <module>
                      ZeroDivisionError: division by zero
                      >>> y
  A variável y        Traceback (most recent call last):
 nunca chega a           File "<stdin>", line 1, in <module>
                      NameError: name 'y' is not defined
   ser criada         >>>
Referências

• Em Python, as variáveis não “contém” objetos,
  apenas referências para objetos

• Isso significa que duas variáveis podem apontar
  para o mesmo objeto
 • Por isso dá certo pensar em variáveis como
    “rótulos”
 • O mesmo objeto pode ter dois rótulos
Atribuição
 • Atribuição nunca faz cópias de objetos!
  • apenas associa rótulos
  • ou muda os rótulos de lugar
a = [1,2,3]    b = a               a = 'zoo'
                       atribuição da
                       variável
                       a
                       ao objeto
                       [1, 2, 3]
Atribuição
 • Atribuição nunca faz cópias de objetos!
  • apenas associa rótulos
  • ou muda os rótulos de lugar
a = [1,2,3]    b = a         a = 'zoo'
Atribuição
 • Atribuição nunca faz cópias de objetos!
  • apenas associa rótulos
  • ou muda os rótulos de lugar
a = [1,2,3]    b = a         a = 'zoo'
Aliasing (“apelidamento”)
        Pelé
Edson
               • Uma pessoa pode ser
                 chamada por dois ou mais
                 nomes diferentes
               • Um objeto pode ser
                 referenciado através de
                 duas ou mais variáveis
                 diferentes
Aliasing: demonstração

>>> a = [21, 52, 73]
>>> b = a
>>> c = a[:]
>>> b is a
True
>>> c is a
False
>>> b == a
True
>>> c == a
True
>>> a, b, c
([21, 52, 73], [21, 52, 73], [21, 52, 73])
>>> b[1] = 999
>>> a, b, c
([21, 999, 73], [21, 999, 73], [21, 52, 73])
Identidade e igualdade
• Use id(o) para ver a identidade de um objeto
• Duas variáveis podem apontar para o mesmo
  objeto
• Neste caso, seus valores são idênticos
 • a is b → True
• Duas variáveis podem apontar para objetos
  distintos com conteúdos iguais

 • a == b   → True
Comparando com Java

• Em Java o operador que compara referências é ==
 • também usado para os tipos primitivos (int etc.)
• Em Python, comparação de referências é com is
 • Este operador não pode ser sobrecarregado
Comparando com Java (2)
• Em Java, igualdade entre objetos é testada com o
  método .equals()
  • .equals() é um método, portanto
    x.equals(y) não funciona se x é null
• Em Python, usamos o operador ==
 • O operador == pode ser sobrecarregado em
    qualquer classe, redefinindo o método __eq__
  • Em Python, None é um objeto e suporta ==
  • Mas o teste x is None é mais eficiente
Programação
orientada a
classes
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
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
• Exemplo de uso:
              $ 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):
          def __init__(self, itens=None):
              self.itens = list(itens) if itens else []

          def carregar(self, itens):
              self.itens.extend(itens)

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

          def misturar(self):
              random.shuffle(self.itens)

          def sortear(self):
              return self.itens.pop()
Herança
Mamifero: superclasse
 de Cao                UML
                                                                  diagrama de classe
class Mamifero(object):
    """lição de casa: implementar"""




                                                 especialização




                                                                                       generalização
class Cao(Mamifero):
    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)
Relógio com classe
import Tkinter
from time import strftime

class Relogio(Tkinter.Label):
    def __init__(self):
        Tkinter.Label.__init__(self)
        self.pack()
        self['text'] = strftime('%H:%M:%S')
        self['font'] = 'Helvetica 120 bold'
        self.tictac()
        
    def tictac(self):
        agora = strftime('%H:%M:%S')
        if agora != self['text']:
            self['text'] = agora
        self.after(100, self.tictac)

rel = Relogio()
rel.mainloop()


            oopy/exemplos/relogio_oo.py
Uma pequena
                                                    parte da
                                                    hierarquia de
                                                    classes do
                                                    Tkinter
                                 herança múltipla


mixin




        he
          ran
             ça
                  mú
                     ltipl
                             a
Um pouco mais da hierarquia de classes do Tkinter
Hierarquia de classes dos objetos gráficos doTkinter
Exemplo de herança
 múltipla no Django
  • Class-based views (CBV): classes para a construção
      de views, desde o Django 1.3
  • Divisão de tarefas para a construção modular de
      views, diminuindo código repetitivo
  • Vamos explorar views básicas e list/detail
API navegável: http://ccbv.co.uk/

Apostila (em desenvolvimento) com diagramas UML:
http://turing.com.br/material/acpython/mod3/django/views1.html
CBV: divisão de tarefas

  tratar o
                            obter e
request e
                           renderizar
produzir o
                           o template
 response
CBV: views de detalhe
   identificar e           tratar
recuperar o objeto   request/response




                                         obter e
                                        renderizar
                                        o template
CBV: views de listagem
   identificar e         tratar
   recuperar a     request/response
lista de objetos




                                       obter e
                                      renderizar
                                      o template
Exemplo de uso de CBV
  • django-ibge: API restful fornecendo JSON para
    JQuery mostrar regiões, estados e municípios
  • No arquivo municipios/views.py:
   • uma subclasse bem simples de ListView
  • No arquivo municipios/api.py
   • 4 subclasses de BaseListView com
      JSONResponseMixin

https://github.com/oturing/django-ibge
Composição
As duas hierarquias
de um sistema OO




               Object-oriented Analysis
               and Design with Applications
               3ed. - Booch et. al.
from Tkinter import Frame, Label, Button




 Timer
               class Timer(Frame):
                   def __init__(self):
                       Frame.__init__(self)
                       self.inicio = self.agora = 15
                       self.pendente = None # alarme pendente
                       self.grid()
                       self.mostrador = Label(self, width=2, anchor='e',
                                              font='Helvetica 120 bold',)
                       self.mostrador.grid(column=0, row=0, sticky='nswe')
                       self.bt_start = Button(self, text='Start', command=self.start)
                       self.bt_start.grid(column=0, row=1, sticky='we')
                       self.atualizar_mostrador()
                       
                   def atualizar_mostrador(self):
                       self.mostrador['text'] = str(self.agora)
                       
                   def start(self):
                       if self.pendente:
                           self.after_cancel(self.pendente)
                       self.agora = self.inicio
                       self.atualizar_mostrador()
                       self.pendente = self.after(1000, self.tictac)



• Exemplo          def tictac(self):
                       self.agora -= 1
                       self.atualizar_mostrador()
  simples de           if self.agora > 0:
                           self.pendente = self.after(1000, self.tictac)

  composição   timer = Timer()
               timer.mainloop()




                     oopy/exemplos/timer.py
from Tkinter import Frame, Label, Button




Timer
        class Timer(Frame):
            def __init__(self):
                Frame.__init__(self)
                self.inicio = self.agora = 15
                self.pendente = None # alarme pendente
                self.grid()
                self.mostrador = Label(self, width=2, anchor='e',
                                       font='Helvetica 120 bold',)
                self.mostrador.grid(column=0, row=0, sticky='nswe')
                self.bt_start = Button(self, text='Start', command=self.start)
                self.bt_start.grid(column=0, row=1, sticky='we')
                self.atualizar_mostrador()
                
            def atualizar_mostrador(self):
                self.mostrador['text'] = str(self.agora)
                
            def start(self):
                if self.pendente:
                    self.after_cancel(self.pendente)
                self.agora = self.inicio
                self.atualizar_mostrador()
                self.pendente = self.after(1000, self.tictac)

            def tictac(self):
                self.agora -= 1
                self.atualizar_mostrador()
                if self.agora > 0:
                    self.pendente = self.after(1000, self.tictac)

        timer = Timer()
        timer.mainloop()




              oopy/exemplos/timer.py
Composição
• Arranjo de partes de
  um sistema             mostrador = Label()


 • componentes,
    sub-componentes...   bt_start = Button()




                         timer = Timer()
from Tkinter import Frame, Label, Button

                     class Timer(Frame):
                         def __init__(self):
                             Frame.__init__(self)
                             self.inicio = self.agora = 15
                             self.pendente = None # alarme pendente
          instan         self.grid()
                 ciaçã
                      o
                             self.mostrador = Label(self, width=2, anchor='e',
                                                    font='Helvetica 120 bold',)
                             self.mostrador.grid(column=0, row=0, sticky='nswe')
                             self.bt_start = Button(self, text='Start', command=self.start)
                     ção
                             self.bt_start.grid(column=0, row=1, sticky='we')
           inst ancia        self.atualizar_mostrador()
                             
                         def atualizar_mostrador(self):
                             self.mostrador['text'] = str(self.agora)
                             
                         def start(self):
                             if self.pendente:
                                 self.after_cancel(self.pendente)
                             self.agora = self.inicio
                             self.atualizar_mostrador()
                             self.pendente = self.after(1000, self.tictac)

                      def tictac(self):
                          self.agora -= 1
                          self.atualizar_mostrador()
                          if self.agora > 0:
                              self.pendente = self.after(1000, self.tictac)
instan
         ciaçã
              o
                  timer = Timer()
                  timer.mainloop()




                        oopy/exemplos/timer.py
Composição em UML




                    composição
                    composição
Composição e herança




                   composição
      composição
Sobrecarga de
operadores
Sobrecarga de operadores
• Python permite que as classes definidas pelo
  usuário (você!) implementem métodos para os
  operadores definidos na linguagem
• Não é possível redefinir a função dos operadores
  nos tipos embutidos
 • isso evita surpresas desagradáveis
• Nem é possível inventar novos operadores
 • não podemos definir ~, <=>, /| etc.
Alguns operadores
 existentes
  • Aritméticos: + - * / ** //
  • Bitwise: & ^ | << >>
  • Acesso a atributos: a.b
  • Invocação: f(x)
  • Operações em coleções: c[a], len(c), a in c, iter(c)
  • Lista completa em Python Reference: Data Model
http://docs.python.org/reference/datamodel.html
Exemplo: vetor (2d)
y
                                          • Campos: x, y
                                          • Métodos:
                                           • distancia
                        Vetor(4, 5)

Vetor(2, 4)


                                           • abs (distância até 0,0)
                                           • + (__add__)
              Vetor(2, 1)
                                      x    • * (__mul__) escalar
                                 oopy/exemplos/vetor.py
Vetor
from math import sqrt

class Vetor(object):

    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __repr__(self):
        return 'Vetor(%s, %s)' % (self.x, self.y)

    def distancia(self, v2):
        dx = self.x - v2.x
        dy = self.y - v2.y                   >>> from vetor import Vetor
        return sqrt(dx*dx + dy*dy)
                                             >>> v = Vetor(3, 4)
    def __abs__(self):                       >>> abs(v)
        return self.distancia(Vetor(0,0))    5.0
                                             >>> v1 = Vetor(2, 4)
    def __add__(self, v2):                   >>> v2 = Vetor(2, 1)
        dx = self.x + v2.x                   >>> v1 + v2
        dy = self.y + v2.y
                                             Vetor(4, 5)
        return Vetor(dx, dy)
                                             >>> v1 * 3
    def __mul__(self, n):                    Vetor(6, 12)
        return Vetor(self.x*n, self.y*n)
Objetos invocáveis
• Você pode definir suas próprias funções...
• E também novas classes de objetos que se
  comportam como funções: objetos invocáveis
 • basta definir um método __call__ para
    sobrecarregar o operador de invocação: ()
   • o(x)
• Exemplo: tômbola invocável
Tômbola invocável
  • Já que o principal uso de uma instância de tômbola
     é sortear, podemos criar um atalho:
     em vez de t.sortear() >>> t = TombolaInvocavel()
     apenas t()               >>> t.carregar([1, 2, 3])
                                    >>> t()
                                    3
from tombola import Tombola         >>> t()
                                    2
class TombolaInvocavel(Tombola):
    '''Sorteia itens sem repetir;
       a instância é invocável como uma função'''

    def __call__(self):
        return self.sortear()
Encapsulamento
Encapsulamento
Propriedades:
  encapsulamento para quem precisa de
  encapsulamento

  >>>   a = C()           violação de
  >>>   a.x = 10       encapsulamento?
  >>>   print a.x
  10
  >>>   a.x = -10
  >>>   print a.x        pergunte-me
  0                         como!
                                         slide
                                          semi
                                            novo
Propriedade: implementação
apenas para leitura, via decorator:

 class C(object):
     def __init__(self, x):
         self.__x = x
     @property
     def x(self):
         return self.__x

a notação __x protege o atributo contra acessos
acidentais (__x = dois underscores à esquerda)
                                                  slide
                                                   semi
                                                     novo
Propriedade: implementação 2
  para leitura e escrita (Python >= 2.2):

class C(object):
    def __init__(self, x=0):
        self.__x = x
    def getx(self):
        return self.__x
    def setx(self, valor):
        self.__x = valor if valor >= 0 else 0
    x = property(getx, setx)

                                                slide
                                                 semi
                                                   novo
Propriedade: implementação 3
  para leitura e escrita (Python >= 2.6):

class C(object):
    def __init__(self, x=0):
        self.__x = x
    @property
    def x(self):
        return self.__x
    @x.setter
    def x(self, valor):
        self.__x = valor if valor >= 0 else 0

                                                slide
                                                 semi
                                                   novo
Propriedade: exemplo de uso
class ContadorTotalizador(Contador):
    def __init__(self):
        super(ContadorTotalizador, self).__init__()
        self.__total = 0

    def incluir(self, item):
        super(ContadorTotalizador, self).incluir(item)
        self.__total += 1

    @property
    def total(self):
        return self.__total


                                                      slide
                                                       semi
                                                         novo
Atributos protegidos
• Atributos protegidos em
  Python são salvaguardas
 • servem para evitar
    atribuição ou sobrescrita
    acidental
 • não para evitar usos (ou
    abusos) intencionais
Atributos protegidos
• Atributos protegidos em
   Python são salvaguardas
  • servem para evita
    atribuição ou sobrescrita
    acidental
  • não para evitar usos (ou
    abusos) intencionais
>>> raisins._LineItem__weight
10
Decoradores
Decoradores de funções
• Exemplos de decoradores:
 • @property, @x.setter, @classmethod
• Não têm relação com o padrão de projeto
  “decorator”
• São funções que recebem a função decorada como
  argumento e produzem uma nova função que
  substitui a função decorada
 • Tema de outro curso...
Decoradores de métodos
• Usados na definição de métodos em classes
 • @property, @x.setter, @x.deleter: definem
    métodos getter, setter e deleter para
    propriedades
 • @classmethod, @staticmethod: definem
    métodos que não precisam de uma instância
    para operar
 • @abstractmethod, @abstractproperty: uso em
    classes abstratas (veremos logo mais)
classmethod x staticmethod
   • Métodos estáticos são como funções simples
      embutidas em uma classe: não recebem
      argumentos automáticos
   • Métodos de classe recebem a classe como
      argumento automático
class Exemplo(object):
                             >>> Exemplo.estatico('bar')
    @staticmethod            'bar'
    def estatico(arg):       >>> Exemplo.da_classe('fu')
        return arg           (<class '__main__.Exemplo'>, 'fu')
    @classmethod
    def da_classe(cls, arg):
        return (cls, arg)
Carta simples
class Carta(object):

    def __init__(self, valor, naipe):
        self.valor = valor
        self.naipe = naipe

    def __repr__(self):
        return 'Carta(%r, %r)' % (self.valor, self.naipe)




                                              >>> zape = Carta('4', 'paus')
                                              >>> zape.valor
                                              '4'
                                              >>> zape
                                              Carta('4', 'paus')
Todas
                                                              as
class Carta(object):

    naipes = 'espadas ouros paus copas'.split()
    valores = '2 3 4 5 6 7 8 9 10 J Q K A'.split()

    def __init__(self, valor, naipe):
        self.valor = valor
        self.naipe = naipe
                                                            cartas
    def __repr__(self):
        return 'Carta(%r, %r)' % (self.valor, self.naipe)

    @classmethod
    def todas(cls):
        return [cls(v, n) for n in cls.naipes
                          for v in cls.valores]


    >>> monte = Carta.todas()
    >>> len(monte)
    52
    >>> monte[0]
    Carta('2', 'espadas')
    >>> monte[-3:]
    [Carta('Q', 'copas'), Carta('K', 'copas'), Carta('A', 'copas')]
Exemplo de classmethod
• É conveniente em todas ter acesso à classe para
  acessar os atributos (naipes, valores) e para
  instanciar as cartas
                    class Carta(object):

                        naipes = 'espadas ouros paus copas'.split()
                        valores = '2 3 4 5 6 7 8 9 10 J Q K A'.split()

                        def __init__(self, valor, naipe):
                            self.valor = valor
                            self.naipe = naipe

                        def __repr__(self):
                            return 'Carta(%r, %r)' % (self.valor,
                    self.naipe)

                        @classmethod
                        def todas(cls):
                            return [cls(v, n) for n in cls.naipes
                                              for v in cls.valores]
Decoradores de classes
   • Novidade do Python 2.6, ainda pouco utilizada na
      prática
   • Exemplo na biblioteca padrão a partir do Python
      2.7:
     • functools.total_ordering define
         automaticamente métodos para os operadores
         de comparação < > <= >=

http://docs.python.org/library/functools.html#functools.total_ordering
from functools import total_ordering                     Cartas
                                                     comparáveis
@total_ordering
class Carta(object):

    naipes = 'espadas ouros paus copas'.split()
    valores = '2 3 4 5 6 7 8 9 10 J Q K A'.split()

    def __init__(self, valor, naipe):
        self.valor = valor
        self.naipe = naipe

    def __repr__(self):
        return 'Carta(%r, %r)' % (self.valor, self.naipe)

    @classmethod
    def todas(cls):
                                                     >>> dois >= as_
        return [cls(v, n) for n in cls.naipes        False
                          for v in cls.valores]      >>> dois <= as_
                                                     True
    def __eq__(self, outra):
        return ((self.valor, self.naipe) ==
                (outra.valor, outra.naipe))

    def peso(self):
        return (Carta.naipes.index(self.naipe) +
            len(Carta.naipes) * Carta.valores.index(self.valor))

    def __gt__(self, outra):
        return self.peso() > outra.peso()
Total ordering == lucro!
>>> mao = [as_, dois, rei]
>>> sorted(mao)
[Carta('2', 'espadas'), Carta('K', 'copas'), Carta('A', 'copas')]


from functools import total_ordering

@total_ordering
class Carta(object):

    # ...várias linhas omitidas...

    def __eq__(self, outra):
        return ((self.valor, self.naipe) ==
                (outra.valor, outra.naipe))

    def peso(self):
        return (Carta.naipes.index(self.naipe) +
            len(Carta.naipes) * Carta.valores.index(self.valor))

    def __gt__(self, outra):
        return self.peso() > outra.peso()
Baralho polimórfico
Polimorfismo: definição
O conceito de “polimorfismo” significa que podemos tratar
instâncias de diferentes classes da mesma maneira.

Assim, podemos enviar uma mensagem a um objeto sem saber
de antemão qual é o seu tipo, e o objeto ainda assim fará “a
coisa certa”, pelo menos do seu ponto de vista.

Scott Ambler - The Object Primer, 2nd ed. - p. 173
Polimorfismo
 Fatiamento e len
   listas e strings são sequências

>>> l = [1, 2, 3]
>>> l[:2]
[1, 2]
>>> 'casa'[:2]
'ca'
>>> len(l)
3
>>> len('casa')
4
                                     slide
                                      semi
                                        novo
Polimorfismo
>>> s = 'Python: simples e correta'
>>> for letra in s[:6]: print letra
P
y
t
h
o
n
>>> for letra in reversed(s): print letra
...
a
t
e
r
                                            slide
r                                            semi
o                                              novo
Polimorfismo
>>>   l = range(10)
>>>   l
[0,   1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>   l[0]
0
>>>   l[-1]
9
>>>   l[:3]
[0,   1, 2]
>>>   for n in reversed(l): print n
...
9
8
7
6
                                      slide
5                                      semi
4                                        novo
Baralho polimórfico 2
métodos especiais: __len__, __getitem__
  com esses métodos, Baralho implementa o
  protocolo das sequências imutáveis

 class Baralho(object):

     def __init__(self):
         self.cartas = Carta.todas()

     def __len__(self):
         return len(self.cartas)

     def __getitem__(self, pos):
                                            slide
         return self.cartas[pos]             semi
                                               novo
Baralho polimórfico 3
>>> from baralho import Baralho
>>> b = Baralho()
>>> len(b)
52
>>> b[0], b[1], b[2]
(<A de paus>, <2 de copas>, <3 de copas>)
>>> for carta in reversed(b): print carta
...
<K de ouros>
<Q de ouros>
<J de ouros>
<10 de ouros>
<9 de ouros>
<8 de ouros>
                                            slide
<7 de ouros>                                 semi
<6 de ouros>                                   novo
Baralho polimórfico 4
>>> from baralho import Baralho
>>> b = Baralho()
>>> len(b)
52
>>> b[:3]
[<A de paus>, <2 de paus>, <3 de paus>]
>>> from random import choice
>>> for i in range(5): print choice(b)
...
<Q de copas>
<4 de ouros>
                                   a mesma carta pode
<A de copas>                         sair duas vezes!
<5 de ouros>
<9 de paus>
>>> for i in range(5): print choice(b)
                                                      slide
...                                                    semi
<3 de paus>                                              novo
Baralho polimórfico 5
>>> from random import shuffle        Python vem com
>>> l = range(10)
>>> l                                 pilhas incluídas!
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> shuffle(l)
>>> l
[7, 6, 3, 2, 9, 5, 0, 4, 1, 8]
>>> shuffle(b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/System/Library/Frameworks/Python.framework/
Versions/2.6/lib/python2.6/random.py", line 275, in
shuffle
    x[i], x[j] = x[j], x[i]
TypeError: 'Baralho' object does not support item
assignment                                              slide
                                                          semi
                       ooops...                            novo
Baralho polimórfico 6
                                             monkey-
>>> def meu_setitem(self, pos, valor):        patch
...     self.cartas[pos] = valor
...
>>> Baralho.__setitem__ = meu_setitem
>>> shuffle(b)                                 agora
>>> b[:5]                                    funciona!
[<J de espadas>, <Q de paus>, <2 de paus>,
<6 de paus>, <A de espadas>]
>>>



                                                    slide
                                                     semi
                                                       novo
Baralho polimórfico 7
fazendo direito (sem monkey-patch)

 class Baralho(object):

     def __init__(self):
         self.cartas = Carta.todas()

     def __len__(self):
         return len(self.cartas)

     def __getitem__(self, pos):
         return self.cartas[pos]

     def __setitem__(self, pos, item):   slide
         self.cartas[pos] = item          semi
                                            novo
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

Mais conteúdo relacionado

Mais procurados

Curso JavaScript - Aula sobre DOM e Ajax
Curso JavaScript - Aula sobre DOM e AjaxCurso JavaScript - Aula sobre DOM e Ajax
Curso JavaScript - Aula sobre DOM e AjaxTiago Antônio da Silva
 
Hadoop - primeiros passos
Hadoop - primeiros passosHadoop - primeiros passos
Hadoop - primeiros passosrhpinotti
 
Aula 02 - Principios da Orientação a Objetos (POO)
Aula 02 - Principios da Orientação a Objetos (POO)Aula 02 - Principios da Orientação a Objetos (POO)
Aula 02 - Principios da Orientação a Objetos (POO)Daniel Brandão
 
Apresentando a Linguagem de Programação Python
Apresentando a Linguagem de Programação PythonApresentando a Linguagem de Programação Python
Apresentando a Linguagem de Programação PythonPriscila Mayumi
 
Laboratório de Programação II: Grafos - Matriz de adjacência e Matriz de inci...
Laboratório de Programação II: Grafos - Matriz de adjacência e Matriz de inci...Laboratório de Programação II: Grafos - Matriz de adjacência e Matriz de inci...
Laboratório de Programação II: Grafos - Matriz de adjacência e Matriz de inci...Alex Camargo
 
01 Introdução à programação web
01 Introdução à programação web01 Introdução à programação web
01 Introdução à programação webCentro Paula Souza
 
Apresentação programação orientada à objetos
Apresentação   programação orientada à objetosApresentação   programação orientada à objetos
Apresentação programação orientada à objetossoncino
 
Aula 02 - Introdução ao PHP
Aula 02 - Introdução ao PHPAula 02 - Introdução ao PHP
Aula 02 - Introdução ao PHPDaniel Brandão
 
Introdução a Linguagem de Programação C
Introdução a Linguagem de Programação CIntrodução a Linguagem de Programação C
Introdução a Linguagem de Programação CGercélia Ramos
 
02 - Orientação a objetos e revisão de C# v1.5
02 - Orientação a objetos e revisão de C# v1.502 - Orientação a objetos e revisão de C# v1.5
02 - Orientação a objetos e revisão de C# v1.5César Augusto Pessôa
 
Banco de Dados I - Aula 05 - Banco de Dados Relacional (Modelo Conceitual)
Banco de Dados I - Aula 05 - Banco de Dados Relacional (Modelo Conceitual)Banco de Dados I - Aula 05 - Banco de Dados Relacional (Modelo Conceitual)
Banco de Dados I - Aula 05 - Banco de Dados Relacional (Modelo Conceitual)Leinylson Fontinele
 
Banco de Dados - MySQL Basico
Banco de Dados - MySQL BasicoBanco de Dados - MySQL Basico
Banco de Dados - MySQL BasicoRangel Javier
 
DOMinando JavaScript
DOMinando JavaScriptDOMinando JavaScript
DOMinando JavaScriptThiago Poiani
 
Introdução a JavaScript
Introdução a JavaScriptIntrodução a JavaScript
Introdução a JavaScriptBruno Catão
 

Mais procurados (20)

Curso JavaScript - Aula sobre DOM e Ajax
Curso JavaScript - Aula sobre DOM e AjaxCurso JavaScript - Aula sobre DOM e Ajax
Curso JavaScript - Aula sobre DOM e Ajax
 
POO - Aula 09 - Herança
POO - Aula 09 - HerançaPOO - Aula 09 - Herança
POO - Aula 09 - Herança
 
Python Interface Gráfica Tkinter
Python Interface Gráfica TkinterPython Interface Gráfica Tkinter
Python Interface Gráfica Tkinter
 
Aula 06 comandos linux
Aula 06   comandos linuxAula 06   comandos linux
Aula 06 comandos linux
 
Hadoop - primeiros passos
Hadoop - primeiros passosHadoop - primeiros passos
Hadoop - primeiros passos
 
Aula 02 - Principios da Orientação a Objetos (POO)
Aula 02 - Principios da Orientação a Objetos (POO)Aula 02 - Principios da Orientação a Objetos (POO)
Aula 02 - Principios da Orientação a Objetos (POO)
 
Apresentando a Linguagem de Programação Python
Apresentando a Linguagem de Programação PythonApresentando a Linguagem de Programação Python
Apresentando a Linguagem de Programação Python
 
Laboratório de Programação II: Grafos - Matriz de adjacência e Matriz de inci...
Laboratório de Programação II: Grafos - Matriz de adjacência e Matriz de inci...Laboratório de Programação II: Grafos - Matriz de adjacência e Matriz de inci...
Laboratório de Programação II: Grafos - Matriz de adjacência e Matriz de inci...
 
Variáveis e portugol
Variáveis e portugolVariáveis e portugol
Variáveis e portugol
 
01 Introdução à programação web
01 Introdução à programação web01 Introdução à programação web
01 Introdução à programação web
 
Apresentação programação orientada à objetos
Apresentação   programação orientada à objetosApresentação   programação orientada à objetos
Apresentação programação orientada à objetos
 
Aula 02 - Introdução ao PHP
Aula 02 - Introdução ao PHPAula 02 - Introdução ao PHP
Aula 02 - Introdução ao PHP
 
Introdução a Linguagem de Programação C
Introdução a Linguagem de Programação CIntrodução a Linguagem de Programação C
Introdução a Linguagem de Programação C
 
02 - Orientação a objetos e revisão de C# v1.5
02 - Orientação a objetos e revisão de C# v1.502 - Orientação a objetos e revisão de C# v1.5
02 - Orientação a objetos e revisão de C# v1.5
 
Banco de Dados I - Aula 05 - Banco de Dados Relacional (Modelo Conceitual)
Banco de Dados I - Aula 05 - Banco de Dados Relacional (Modelo Conceitual)Banco de Dados I - Aula 05 - Banco de Dados Relacional (Modelo Conceitual)
Banco de Dados I - Aula 05 - Banco de Dados Relacional (Modelo Conceitual)
 
Aula 09 - introducao oo
Aula 09 - introducao ooAula 09 - introducao oo
Aula 09 - introducao oo
 
Banco de Dados - MySQL Basico
Banco de Dados - MySQL BasicoBanco de Dados - MySQL Basico
Banco de Dados - MySQL Basico
 
DOMinando JavaScript
DOMinando JavaScriptDOMinando JavaScript
DOMinando JavaScript
 
Introdução a JavaScript
Introdução a JavaScriptIntrodução a JavaScript
Introdução a JavaScript
 
Python - Introdução
Python - IntroduçãoPython - Introdução
Python - Introdução
 

Semelhante a Orientação a objetos em Python (compacto)

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
 
Iteraveis e geradores em Python
Iteraveis e geradores em PythonIteraveis e geradores em Python
Iteraveis e geradores em PythonLuciano 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
 
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
 
Python: Iteraveis, geradores etc
Python: Iteraveis, geradores etcPython: Iteraveis, geradores etc
Python: Iteraveis, geradores etcLuciano Ramalho
 
Jython no JavaOne Latin America 2011
Jython no JavaOne Latin America 2011Jython no JavaOne Latin America 2011
Jython no JavaOne Latin America 2011Luciano Ramalho
 
Python e seus desafios
Python e seus desafiosPython e seus desafios
Python e seus desafiosJhonathan Davi
 
Estruturas de dados em Python
Estruturas de dados em PythonEstruturas de dados em Python
Estruturas de dados em PythonRicardo Paiva
 
Desenvolvendo com mongodb
Desenvolvendo com mongodbDesenvolvendo com mongodb
Desenvolvendo com mongodbThiago Avelino
 
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
 
Minicurso Básico de Python - PythonDay
Minicurso Básico de Python - PythonDayMinicurso Básico de Python - PythonDay
Minicurso Básico de Python - PythonDayDilan Nery Lopes
 
Palestra python
Palestra pythonPalestra python
Palestra pythonRony Cruch
 
Python e django na prática
Python e django na práticaPython e django na prática
Python e django na práticaRafael Cassau
 
Minicurso: Python em 4 horas - FATEC SCS 2015
Minicurso: Python em 4 horas - FATEC SCS 2015 Minicurso: Python em 4 horas - FATEC SCS 2015
Minicurso: Python em 4 horas - FATEC SCS 2015 Alan Justino da Silva
 

Semelhante a Orientação a objetos em Python (compacto) (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
 
Python
PythonPython
Python
 
Iteraveis e geradores em Python
Iteraveis e geradores em PythonIteraveis e geradores em Python
Iteraveis e geradores em 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
 
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: Iteraveis, geradores etc
Python: Iteraveis, geradores etcPython: Iteraveis, geradores etc
Python: Iteraveis, geradores etc
 
Jython no JavaOne Latin America 2011
Jython no JavaOne Latin America 2011Jython no JavaOne Latin America 2011
Jython no JavaOne Latin America 2011
 
Python e seus desafios
Python e seus desafiosPython e seus desafios
Python e seus desafios
 
Estruturas de dados em Python
Estruturas de dados em PythonEstruturas de dados em Python
Estruturas de dados em Python
 
Desenvolvendo com mongodb
Desenvolvendo com mongodbDesenvolvendo com mongodb
Desenvolvendo com mongodb
 
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 ?
 
Minicurso Básico de Python - PythonDay
Minicurso Básico de Python - PythonDayMinicurso Básico de Python - PythonDay
Minicurso Básico de Python - PythonDay
 
Introdução à Linguagem Ruby
Introdução à Linguagem RubyIntrodução à Linguagem Ruby
Introdução à Linguagem Ruby
 
Python2.5.ppt
Python2.5.pptPython2.5.ppt
Python2.5.ppt
 
Introdução a linguagem Python 2.7
Introdução a linguagem Python 2.7Introdução a linguagem Python 2.7
Introdução a linguagem Python 2.7
 
Palestra python
Palestra pythonPalestra python
Palestra python
 
Python e django na prática
Python e django na práticaPython e django na prática
Python e django na prática
 
Minicurso de jQuery
Minicurso de jQueryMinicurso de jQuery
Minicurso de jQuery
 
Minicurso: Python em 4 horas - FATEC SCS 2015
Minicurso: Python em 4 horas - FATEC SCS 2015 Minicurso: Python em 4 horas - FATEC SCS 2015
Minicurso: Python em 4 horas - FATEC SCS 2015
 

Mais de Luciano Ramalho

Introdução a linguagem Python
Introdução a linguagem PythonIntrodução a linguagem Python
Introdução a linguagem PythonLuciano Ramalho
 
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
 
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
 

Mais de Luciano Ramalho (20)

Wiki-wiki S/A
Wiki-wiki S/AWiki-wiki S/A
Wiki-wiki S/A
 
Mongodb: agregação
Mongodb: agregaçãoMongodb: agregação
Mongodb: agregação
 
Introdução a linguagem Python
Introdução a linguagem PythonIntrodução a linguagem Python
Introdução a linguagem Python
 
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)
 
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
 

Orientação a objetos em Python (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
  • 3. Conceito: “objeto” • Um componente de software que inclui dados (campos) e comportamentos (métodos) • Em geral, os campos 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
  • 4. Terminologia pythonica • Objetos possuem atributos • Os atributos de um objeto podem ser: • métodos funções vinculadas • atributos de dados “campos” Figuras: bycicle (bicicleta), The Java Tutorial http://docs.oracle.com/javase/tutorial/java/concepts/object.html
  • 5. 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.
  • 6. 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']
  • 7. 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'}
  • 8. 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)
  • 9. 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
  • 10. Exercício: construir e controlar Tkinter.Label import Tkinter rel = Tkinter.Label() rel['text'] = '10:42:29' rel.grid() rel['font'] = 'Helvetica 120 bold' from time import strftime rel['text'] = strftime('%H:%M:%S') def tic():     rel['text'] = strftime('%H:%M:%S')      Para instalar def tac(): tic() Tkinter no     rel.after(100, tac) Ubuntu Linux: tac() $ sudo apt-get install python-tk
  • 11. 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'>
  • 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. Tipos
  • 15. Alguns tipos básicos >>> i = 7 Python 2.7 >>> i = 7 Python 3.2 >>> type(i) >>> type(i) <type 'int'> <class 'int'> >>> j = 2**100 >>> j = 2**100 >>> type(j) int e long >>> type(j) <type 'long'> unificados no <class 'int'> >>> f = 7. Python 3 >>> f = 7. >>> type(f) >>> type(f) <type 'float'> <class 'float'> >>> s = 'abc' >>> s = 'abc' >>> type(s) str >>> type(s) <type 'str'> x <class 'str'> SyntaxError >>> u = u'abc' unicode >>> u = u'abc' ou >>> type(u) x <type 'unicode'> <class ‘s tr’> bytes >>> b = b'ABC' >>> b = b'ABC' (Python 3.3) >>> type(b) >>> type(b) <type 'str'> <class 'bytes'> >>> b[0] >>> b[0] 'A' 65
  • 16. Tipos embutidos (built-in) • Implementados em C, por eficiência • Métodos inalteráveis (como “final”, em Java) • Texto: str, unicode (Python 2 e Python 3) • Números: int, long (Python 2), float, complex, bool • Coleções: list, tuple, dict, set, frozenset, bytes (Python 3) • etc.
  • 17. Tipagem forte • O tipo de um objeto nunca muda, e não existem “tipos variantes” • Raramente Python faz conversão automática >>> 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'
  • 18. 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'
  • 19. 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
  • 20. Mutabilidade • Em Python, alguns objetos são mutáveis, outros são imutáveis • Objetos mutáveis possuem conteúdo ou estado interno (atributos de dados) que podem ser alterados ao longo da sua existência • Objetos imutáveis não podem alterados de nenhuma maneira. Seu estado é congelado no momento da inicialização.
  • 21. Mutabilidade: exemplos Mutáveis Imutáveis • list • tuple • dict • str, unicode, bytes • set • frozenset • objetos que permitem a • int, float, complex alteração de atributos por acesso direto, setters ou outros métodos
  • 23. Variáveis não são “caixas”! • Abandone essa idéia! • Ela é válida em C e Pascal, mas não em Python ou Java • Variáveis são rótulos (ou post-its) que identificam objetos • O objeto identificado já existe quando o rótulo é atribuído
  • 24. Objetos e variáveis • Objetos existem antes das variáveis • Em uma atribuição, o lado direito do = é executado primeiro. Prova: Primeiro o objeto >>> x = 10 >>> x 10 é criado, 10 depois a variável >>> y = 7 / 0 a é atribuída a ele Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: division by zero >>> y A variável y Traceback (most recent call last): nunca chega a File "<stdin>", line 1, in <module> NameError: name 'y' is not defined ser criada >>>
  • 25. Referências • Em Python, as variáveis não “contém” objetos, apenas referências para objetos • Isso significa que duas variáveis podem apontar para o mesmo objeto • Por isso dá certo pensar em variáveis como “rótulos” • O mesmo objeto pode ter dois rótulos
  • 26. Atribuição • Atribuição nunca faz cópias de objetos! • apenas associa rótulos • ou muda os rótulos de lugar a = [1,2,3] b = a a = 'zoo' atribuição da variável a ao objeto [1, 2, 3]
  • 27. Atribuição • Atribuição nunca faz cópias de objetos! • apenas associa rótulos • ou muda os rótulos de lugar a = [1,2,3] b = a a = 'zoo'
  • 28. Atribuição • Atribuição nunca faz cópias de objetos! • apenas associa rótulos • ou muda os rótulos de lugar a = [1,2,3] b = a a = 'zoo'
  • 29. Aliasing (“apelidamento”) Pelé Edson • Uma pessoa pode ser chamada por dois ou mais nomes diferentes • Um objeto pode ser referenciado através de duas ou mais variáveis diferentes
  • 30. Aliasing: demonstração >>> a = [21, 52, 73] >>> b = a >>> c = a[:] >>> b is a True >>> c is a False >>> b == a True >>> c == a True >>> a, b, c ([21, 52, 73], [21, 52, 73], [21, 52, 73]) >>> b[1] = 999 >>> a, b, c ([21, 999, 73], [21, 999, 73], [21, 52, 73])
  • 31. Identidade e igualdade • Use id(o) para ver a identidade de um objeto • Duas variáveis podem apontar para o mesmo objeto • Neste caso, seus valores são idênticos • a is b → True • Duas variáveis podem apontar para objetos distintos com conteúdos iguais • a == b → True
  • 32. Comparando com Java • Em Java o operador que compara referências é == • também usado para os tipos primitivos (int etc.) • Em Python, comparação de referências é com is • Este operador não pode ser sobrecarregado
  • 33. Comparando com Java (2) • Em Java, igualdade entre objetos é testada com o método .equals() • .equals() é um método, portanto x.equals(y) não funciona se x é null • Em Python, usamos o operador == • O operador == pode ser sobrecarregado em qualquer classe, redefinindo o método __eq__ • Em Python, None é um objeto e suporta == • Mas o teste x is None é mais eficiente
  • 35. 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
  • 36. Exemplar de cão: instância da classe Cao >>> rex = Cao() instanciação
  • 37. 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
  • 38. 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)
  • 39. 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
  • 40. >>> 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
  • 41. 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
  • 42. 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
  • 43. Interface da tômbola • Carregar itens • Misturar itens • Sortear um item • Indicar se há mais itens
  • 44. Projeto da tômbola • UML: diagrama de classe
  • 45. 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ê)
  • 46. 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 • Exemplo de uso: $ python -m doctest cao.rst oopy/exemplos/cao.rst
  • 47. Coding Dojo • Implementação da classe Tombola, com testes feitos em Doctest
  • 48. Implementação da tômbola # coding: utf-8 import random class Tombola(object): def __init__(self, itens=None): self.itens = list(itens) if itens else [] def carregar(self, itens): self.itens.extend(itens) def carregada(self): return bool(self.itens) def misturar(self): random.shuffle(self.itens) def sortear(self): return self.itens.pop()
  • 50. Mamifero: superclasse de Cao UML diagrama de classe class Mamifero(object):     """lição de casa: implementar""" especialização generalização class Cao(Mamifero):     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
  • 51. 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)
  • 52. 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)
  • 53. 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)
  • 54. Relógio com classe import Tkinter from time import strftime class Relogio(Tkinter.Label):     def __init__(self):         Tkinter.Label.__init__(self)         self.pack()         self['text'] = strftime('%H:%M:%S')         self['font'] = 'Helvetica 120 bold'         self.tictac()              def tictac(self):         agora = strftime('%H:%M:%S')         if agora != self['text']:             self['text'] = agora         self.after(100, self.tictac) rel = Relogio() rel.mainloop() oopy/exemplos/relogio_oo.py
  • 55. Uma pequena parte da hierarquia de classes do Tkinter herança múltipla mixin he ran ça mú ltipl a
  • 56. Um pouco mais da hierarquia de classes do Tkinter
  • 57. Hierarquia de classes dos objetos gráficos doTkinter
  • 58. Exemplo de herança múltipla no Django • Class-based views (CBV): classes para a construção de views, desde o Django 1.3 • Divisão de tarefas para a construção modular de views, diminuindo código repetitivo • Vamos explorar views básicas e list/detail API navegável: http://ccbv.co.uk/ Apostila (em desenvolvimento) com diagramas UML: http://turing.com.br/material/acpython/mod3/django/views1.html
  • 59. CBV: divisão de tarefas tratar o obter e request e renderizar produzir o o template response
  • 60. CBV: views de detalhe identificar e tratar recuperar o objeto request/response obter e renderizar o template
  • 61. CBV: views de listagem identificar e tratar recuperar a request/response lista de objetos obter e renderizar o template
  • 62. Exemplo de uso de CBV • django-ibge: API restful fornecendo JSON para JQuery mostrar regiões, estados e municípios • No arquivo municipios/views.py: • uma subclasse bem simples de ListView • No arquivo municipios/api.py • 4 subclasses de BaseListView com JSONResponseMixin https://github.com/oturing/django-ibge
  • 64. As duas hierarquias de um sistema OO Object-oriented Analysis and Design with Applications 3ed. - Booch et. al.
  • 65. from Tkinter import Frame, Label, Button Timer class Timer(Frame):     def __init__(self):         Frame.__init__(self)         self.inicio = self.agora = 15         self.pendente = None # alarme pendente         self.grid()         self.mostrador = Label(self, width=2, anchor='e',                                font='Helvetica 120 bold',)         self.mostrador.grid(column=0, row=0, sticky='nswe')         self.bt_start = Button(self, text='Start', command=self.start)         self.bt_start.grid(column=0, row=1, sticky='we')         self.atualizar_mostrador()              def atualizar_mostrador(self):         self.mostrador['text'] = str(self.agora)              def start(self):         if self.pendente:             self.after_cancel(self.pendente)         self.agora = self.inicio         self.atualizar_mostrador()         self.pendente = self.after(1000, self.tictac) • Exemplo     def tictac(self):         self.agora -= 1         self.atualizar_mostrador() simples de         if self.agora > 0:             self.pendente = self.after(1000, self.tictac) composição timer = Timer() timer.mainloop() oopy/exemplos/timer.py
  • 66. from Tkinter import Frame, Label, Button Timer class Timer(Frame):     def __init__(self):         Frame.__init__(self)         self.inicio = self.agora = 15         self.pendente = None # alarme pendente         self.grid()         self.mostrador = Label(self, width=2, anchor='e',                                font='Helvetica 120 bold',)         self.mostrador.grid(column=0, row=0, sticky='nswe')         self.bt_start = Button(self, text='Start', command=self.start)         self.bt_start.grid(column=0, row=1, sticky='we')         self.atualizar_mostrador()              def atualizar_mostrador(self):         self.mostrador['text'] = str(self.agora)              def start(self):         if self.pendente:             self.after_cancel(self.pendente)         self.agora = self.inicio         self.atualizar_mostrador()         self.pendente = self.after(1000, self.tictac)     def tictac(self):         self.agora -= 1         self.atualizar_mostrador()         if self.agora > 0:             self.pendente = self.after(1000, self.tictac) timer = Timer() timer.mainloop() oopy/exemplos/timer.py
  • 67. Composição • Arranjo de partes de um sistema mostrador = Label() • componentes, sub-componentes... bt_start = Button() timer = Timer()
  • 68. from Tkinter import Frame, Label, Button class Timer(Frame):     def __init__(self):         Frame.__init__(self)         self.inicio = self.agora = 15         self.pendente = None # alarme pendente instan         self.grid() ciaçã o         self.mostrador = Label(self, width=2, anchor='e',                                font='Helvetica 120 bold',)         self.mostrador.grid(column=0, row=0, sticky='nswe')         self.bt_start = Button(self, text='Start', command=self.start) ção         self.bt_start.grid(column=0, row=1, sticky='we') inst ancia        self.atualizar_mostrador()              def atualizar_mostrador(self):         self.mostrador['text'] = str(self.agora)              def start(self):         if self.pendente:             self.after_cancel(self.pendente)         self.agora = self.inicio         self.atualizar_mostrador()         self.pendente = self.after(1000, self.tictac)     def tictac(self):         self.agora -= 1         self.atualizar_mostrador()         if self.agora > 0:             self.pendente = self.after(1000, self.tictac) instan ciaçã o timer = Timer() timer.mainloop() oopy/exemplos/timer.py
  • 69. Composição em UML composição composição
  • 70. Composição e herança composição composição
  • 72. Sobrecarga de operadores • Python permite que as classes definidas pelo usuário (você!) implementem métodos para os operadores definidos na linguagem • Não é possível redefinir a função dos operadores nos tipos embutidos • isso evita surpresas desagradáveis • Nem é possível inventar novos operadores • não podemos definir ~, <=>, /| etc.
  • 73. Alguns operadores existentes • Aritméticos: + - * / ** // • Bitwise: & ^ | << >> • Acesso a atributos: a.b • Invocação: f(x) • Operações em coleções: c[a], len(c), a in c, iter(c) • Lista completa em Python Reference: Data Model http://docs.python.org/reference/datamodel.html
  • 74. Exemplo: vetor (2d) y • Campos: x, y • Métodos: • distancia Vetor(4, 5) Vetor(2, 4) • abs (distância até 0,0) • + (__add__) Vetor(2, 1) x • * (__mul__) escalar oopy/exemplos/vetor.py
  • 75. Vetor from math import sqrt class Vetor(object): def __init__(self, x=0, y=0): self.x = x self.y = y def __repr__(self): return 'Vetor(%s, %s)' % (self.x, self.y) def distancia(self, v2): dx = self.x - v2.x dy = self.y - v2.y >>> from vetor import Vetor return sqrt(dx*dx + dy*dy) >>> v = Vetor(3, 4) def __abs__(self): >>> abs(v) return self.distancia(Vetor(0,0)) 5.0 >>> v1 = Vetor(2, 4) def __add__(self, v2): >>> v2 = Vetor(2, 1) dx = self.x + v2.x >>> v1 + v2 dy = self.y + v2.y Vetor(4, 5) return Vetor(dx, dy) >>> v1 * 3 def __mul__(self, n): Vetor(6, 12) return Vetor(self.x*n, self.y*n)
  • 76. Objetos invocáveis • Você pode definir suas próprias funções... • E também novas classes de objetos que se comportam como funções: objetos invocáveis • basta definir um método __call__ para sobrecarregar o operador de invocação: () • o(x) • Exemplo: tômbola invocável
  • 77. Tômbola invocável • Já que o principal uso de uma instância de tômbola é sortear, podemos criar um atalho: em vez de t.sortear() >>> t = TombolaInvocavel() apenas t() >>> t.carregar([1, 2, 3]) >>> t() 3 from tombola import Tombola >>> t() 2 class TombolaInvocavel(Tombola): '''Sorteia itens sem repetir; a instância é invocável como uma função''' def __call__(self): return self.sortear()
  • 79. Encapsulamento Propriedades: encapsulamento para quem precisa de encapsulamento >>> a = C() violação de >>> a.x = 10 encapsulamento? >>> print a.x 10 >>> a.x = -10 >>> print a.x pergunte-me 0 como! slide semi novo
  • 80. Propriedade: implementação apenas para leitura, via decorator: class C(object): def __init__(self, x): self.__x = x @property def x(self): return self.__x a notação __x protege o atributo contra acessos acidentais (__x = dois underscores à esquerda) slide semi novo
  • 81. Propriedade: implementação 2 para leitura e escrita (Python >= 2.2): class C(object): def __init__(self, x=0): self.__x = x def getx(self): return self.__x def setx(self, valor): self.__x = valor if valor >= 0 else 0 x = property(getx, setx) slide semi novo
  • 82. Propriedade: implementação 3 para leitura e escrita (Python >= 2.6): class C(object): def __init__(self, x=0): self.__x = x @property def x(self): return self.__x @x.setter def x(self, valor): self.__x = valor if valor >= 0 else 0 slide semi novo
  • 83. Propriedade: exemplo de uso class ContadorTotalizador(Contador): def __init__(self): super(ContadorTotalizador, self).__init__() self.__total = 0 def incluir(self, item): super(ContadorTotalizador, self).incluir(item) self.__total += 1 @property def total(self): return self.__total slide semi novo
  • 84. Atributos protegidos • Atributos protegidos em Python são salvaguardas • servem para evitar atribuição ou sobrescrita acidental • não para evitar usos (ou abusos) intencionais
  • 85. Atributos protegidos • Atributos protegidos em Python são salvaguardas • servem para evita atribuição ou sobrescrita acidental • não para evitar usos (ou abusos) intencionais >>> raisins._LineItem__weight 10
  • 87. Decoradores de funções • Exemplos de decoradores: • @property, @x.setter, @classmethod • Não têm relação com o padrão de projeto “decorator” • São funções que recebem a função decorada como argumento e produzem uma nova função que substitui a função decorada • Tema de outro curso...
  • 88. Decoradores de métodos • Usados na definição de métodos em classes • @property, @x.setter, @x.deleter: definem métodos getter, setter e deleter para propriedades • @classmethod, @staticmethod: definem métodos que não precisam de uma instância para operar • @abstractmethod, @abstractproperty: uso em classes abstratas (veremos logo mais)
  • 89. classmethod x staticmethod • Métodos estáticos são como funções simples embutidas em uma classe: não recebem argumentos automáticos • Métodos de classe recebem a classe como argumento automático class Exemplo(object): >>> Exemplo.estatico('bar') @staticmethod 'bar' def estatico(arg): >>> Exemplo.da_classe('fu') return arg (<class '__main__.Exemplo'>, 'fu') @classmethod def da_classe(cls, arg): return (cls, arg)
  • 90. Carta simples class Carta(object): def __init__(self, valor, naipe): self.valor = valor self.naipe = naipe def __repr__(self): return 'Carta(%r, %r)' % (self.valor, self.naipe) >>> zape = Carta('4', 'paus') >>> zape.valor '4' >>> zape Carta('4', 'paus')
  • 91. Todas as class Carta(object): naipes = 'espadas ouros paus copas'.split() valores = '2 3 4 5 6 7 8 9 10 J Q K A'.split() def __init__(self, valor, naipe): self.valor = valor self.naipe = naipe cartas def __repr__(self): return 'Carta(%r, %r)' % (self.valor, self.naipe) @classmethod def todas(cls): return [cls(v, n) for n in cls.naipes for v in cls.valores] >>> monte = Carta.todas() >>> len(monte) 52 >>> monte[0] Carta('2', 'espadas') >>> monte[-3:] [Carta('Q', 'copas'), Carta('K', 'copas'), Carta('A', 'copas')]
  • 92. Exemplo de classmethod • É conveniente em todas ter acesso à classe para acessar os atributos (naipes, valores) e para instanciar as cartas class Carta(object): naipes = 'espadas ouros paus copas'.split() valores = '2 3 4 5 6 7 8 9 10 J Q K A'.split() def __init__(self, valor, naipe): self.valor = valor self.naipe = naipe def __repr__(self): return 'Carta(%r, %r)' % (self.valor, self.naipe) @classmethod def todas(cls): return [cls(v, n) for n in cls.naipes for v in cls.valores]
  • 93. Decoradores de classes • Novidade do Python 2.6, ainda pouco utilizada na prática • Exemplo na biblioteca padrão a partir do Python 2.7: • functools.total_ordering define automaticamente métodos para os operadores de comparação < > <= >= http://docs.python.org/library/functools.html#functools.total_ordering
  • 94. from functools import total_ordering Cartas comparáveis @total_ordering class Carta(object): naipes = 'espadas ouros paus copas'.split() valores = '2 3 4 5 6 7 8 9 10 J Q K A'.split() def __init__(self, valor, naipe): self.valor = valor self.naipe = naipe def __repr__(self): return 'Carta(%r, %r)' % (self.valor, self.naipe) @classmethod def todas(cls): >>> dois >= as_ return [cls(v, n) for n in cls.naipes False for v in cls.valores] >>> dois <= as_ True def __eq__(self, outra): return ((self.valor, self.naipe) == (outra.valor, outra.naipe)) def peso(self): return (Carta.naipes.index(self.naipe) + len(Carta.naipes) * Carta.valores.index(self.valor)) def __gt__(self, outra): return self.peso() > outra.peso()
  • 95. Total ordering == lucro! >>> mao = [as_, dois, rei] >>> sorted(mao) [Carta('2', 'espadas'), Carta('K', 'copas'), Carta('A', 'copas')] from functools import total_ordering @total_ordering class Carta(object): # ...várias linhas omitidas... def __eq__(self, outra): return ((self.valor, self.naipe) == (outra.valor, outra.naipe)) def peso(self): return (Carta.naipes.index(self.naipe) + len(Carta.naipes) * Carta.valores.index(self.valor)) def __gt__(self, outra): return self.peso() > outra.peso()
  • 97. Polimorfismo: definição O conceito de “polimorfismo” significa que podemos tratar instâncias de diferentes classes da mesma maneira. Assim, podemos enviar uma mensagem a um objeto sem saber de antemão qual é o seu tipo, e o objeto ainda assim fará “a coisa certa”, pelo menos do seu ponto de vista. Scott Ambler - The Object Primer, 2nd ed. - p. 173
  • 98. Polimorfismo Fatiamento e len listas e strings são sequências >>> l = [1, 2, 3] >>> l[:2] [1, 2] >>> 'casa'[:2] 'ca' >>> len(l) 3 >>> len('casa') 4 slide semi novo
  • 99. Polimorfismo >>> s = 'Python: simples e correta' >>> for letra in s[:6]: print letra P y t h o n >>> for letra in reversed(s): print letra ... a t e r slide r semi o novo
  • 100. Polimorfismo >>> l = range(10) >>> l [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> l[0] 0 >>> l[-1] 9 >>> l[:3] [0, 1, 2] >>> for n in reversed(l): print n ... 9 8 7 6 slide 5 semi 4 novo
  • 101. Baralho polimórfico 2 métodos especiais: __len__, __getitem__ com esses métodos, Baralho implementa o protocolo das sequências imutáveis class Baralho(object): def __init__(self): self.cartas = Carta.todas() def __len__(self): return len(self.cartas) def __getitem__(self, pos): slide return self.cartas[pos] semi novo
  • 102. Baralho polimórfico 3 >>> from baralho import Baralho >>> b = Baralho() >>> len(b) 52 >>> b[0], b[1], b[2] (<A de paus>, <2 de copas>, <3 de copas>) >>> for carta in reversed(b): print carta ... <K de ouros> <Q de ouros> <J de ouros> <10 de ouros> <9 de ouros> <8 de ouros> slide <7 de ouros> semi <6 de ouros> novo
  • 103. Baralho polimórfico 4 >>> from baralho import Baralho >>> b = Baralho() >>> len(b) 52 >>> b[:3] [<A de paus>, <2 de paus>, <3 de paus>] >>> from random import choice >>> for i in range(5): print choice(b) ... <Q de copas> <4 de ouros> a mesma carta pode <A de copas> sair duas vezes! <5 de ouros> <9 de paus> >>> for i in range(5): print choice(b) slide ... semi <3 de paus> novo
  • 104. Baralho polimórfico 5 >>> from random import shuffle Python vem com >>> l = range(10) >>> l pilhas incluídas! [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> shuffle(l) >>> l [7, 6, 3, 2, 9, 5, 0, 4, 1, 8] >>> shuffle(b) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/System/Library/Frameworks/Python.framework/ Versions/2.6/lib/python2.6/random.py", line 275, in shuffle x[i], x[j] = x[j], x[i] TypeError: 'Baralho' object does not support item assignment slide semi ooops... novo
  • 105. Baralho polimórfico 6 monkey- >>> def meu_setitem(self, pos, valor): patch ... self.cartas[pos] = valor ... >>> Baralho.__setitem__ = meu_setitem >>> shuffle(b) agora >>> b[:5] funciona! [<J de espadas>, <Q de paus>, <2 de paus>, <6 de paus>, <A de espadas>] >>> slide semi novo
  • 106. Baralho polimórfico 7 fazendo direito (sem monkey-patch) class Baralho(object): def __init__(self): self.cartas = Carta.todas() def __len__(self): return len(self.cartas) def __getitem__(self, pos): return self.cartas[pos] def __setitem__(self, pos, item): slide self.cartas[pos] = item semi novo
  • 107. 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