Vous êtes sur la page 1sur 48

Introduo

Orientao a Objetos
em Python (sem sotaque)
Luciano Ramalho
luciano@ramalho.org
Wednesday, November 2, 2011

Saiu em uma revista...

Wednesday, November 2, 2011

Python
com
sotaque
javans

Wednesday, November 2, 2011

No use
; no final
das linhas
No um erro
sinttico, mas
desnecessrio
e portanto
deselegante
Wednesday, November 2, 2011

Esses
no so
mtodos
da classe
Esses mtodos
agem sobre as
instncias (note
o self). Mtodos
de classe so
decorados com
@classmethod.
Wednesday, November 2, 2011

No
abuse de
getters e
setters
Em Python no
usamos muitos
getters e setters
dessa forma.
Para controlar
acesso usamos
properties.
Wednesday, November 2, 2011

Caractersticas bsicas

Wednesday, November 2, 2011

OO em Python se
parece com...
herana mltipla, como C++
sobrecarga de operadores, como C++
no obriga a criar classes, como C++
tipagem dinmica, como Smalltalk e Ruby
tipagem dinmica, mas no tipagem fraca

Wednesday, November 2, 2011

O que tipagem fraca?


converso automtica entre tipos
comum em linguagens de scripting (JavaScript, Perl, PHP)
uma fonte de bugs difceis de localizar e tratar
"9" + 10
"910"
- "9" * 10
90
- "9" - 10
-1
- "9" + (-10)
"9-10"
Wednesday, November 2, 2011

Exemplos reais digitados


no console JavaScript do
Firefox 6.0

Ateno: Python
no assim!

Tipagem dinmica
Variveis (e parmetros) no tm tipos declarados e
podem ser associados a objetos de qualquer tipo
em tempo de execuo
Tambm conhecida como duck typing (tipagem
pato) nas comunidades Python, Ruby e Smalltalk
>>> def dobro(n):
...
'''devolve duas vezes n'''
...
return n + n
...
>>> dobro(7)
14
>>> dobro('Spam')
'SpamSpam'
>>> dobro([10, 20, 30])
[10, 20, 30, 10, 20, 30]
Wednesday, November 2, 2011

Tipagem dinmica forte


Python no faz converso automtica de tipos
excees, por praticidade:

int long float


str unicode

>>> "9" + 10
TypeError: cannot concatenate 'str' and 'int' objects
>>> "9" * 10
'9999999999'
>>> "9" - 10
TypeError: unsupported operand type(s) for -: 'str'
and 'int'
>>> "9" + (-10)
TypeError: cannot concatenate 'str' and 'int' objects

Wednesday, November 2, 2011

Para quem conhece Java


Python no tem interfaces
mas tem herana mltipla e classes abstratas
Python no tem sobrecarga de mtodos
mas tem sobrecarga de operadores e passagem de
argumentos flexvel
Python no tem tipos primitivos
tudo objeto (desde Python 2.2, dez/2001)
>>> 5 .__add__(3)
8
Wednesday, November 2, 2011

Ex: 5 uma instncia de int


>>> 5 .__add__(3)
8
atributos de int
>>> type(5)
<type 'int'>
>>> dir(5)
['__abs__', '__add__', '__and__', '__class__', '__cmp__',
'__coerce__', '__delattr__', '__div__', '__divmod__',
'__doc__', '__float__', '__floordiv__', '__format__',
'__getattribute__', '__getnewargs__', '__hash__', '__hex__',
'__index__', '__init__', '__int__', '__invert__',
'__long__', '__lshift__', '__mod__', '__mul__', '__neg__',
'__new__', '__nonzero__', '__oct__', '__or__', '__pos__',
'__pow__', '__radd__', '__rand__', '__rdiv__',
'__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__',
'__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__',
'__ror__', '__rpow__', '__rrshift__', '__rshift__',
'__rsub__', '__rtruediv__', '__rxor__', '__setattr__',
'__sizeof__', '__str__', '__sub__', '__subclasshook__',
'__truediv__', '__trunc__', '__xor__', 'conjugate',
'denominator', 'imag', 'numerator', 'real']
Wednesday, November 2, 2011

Sintaxe de classes

Wednesday, November 2, 2011

Classe com 3 mtodos


class Contador(object):
def __init__(this):
this.contagem = {}
def incluir(this, item):
qtd = this.contagem.get(item, 0) + 1
this.contagem[item] = qtd
def contar(this, item):
return this.contagem[item]

Wednesday, November 2, 2011

Classe com 3 mtodos


class Contador(object):
def __init__(this):
this.contagem = {}

no usamos
this

def incluir(this, item):


qtd = this.contagem.get(item, 0) + 1
this.contagem[item] = qtd
def contar(this, item):
return this.contagem[item]

Wednesday, November 2, 2011

Classe com 3 mtodos


class Contador(object):
def __init__(self):
self.contagem = {}

usamos
self

def incluir(self, item):


qtd = self.contagem.get(item, 0) + 1
self.contagem[item] = qtd
def contar(self, item):
return self.contagem[item]

Wednesday, November 2, 2011

Peculiaridade: self explcito


Todos os mtodos de instncias devem declarar o self
como primeiro parmetro
Todos os acessos a atributos (inclusive mtodos) das
instncias devem ser feitos via referncia explcita a self
class Contador(object):
def __init__(self):
self.contagem = {}
def incluir(self, item):
qtd = self.contagem.get(item, 0) + 1
self.contagem[item] = qtd
Wednesday, November 2, 2011

Ex: uso da classe Contador


>>>
>>>
>>>
...
...
>>>
...
...
a 3
b 1
c 1
i 1
x 1

cont = Contador()
palavra = 'abacaxi'
for letra in palavra:
cont.incluir(letra)

no existe o
operador new

for letra in sorted(set(pal)):


print letra, cont.contar(letra)

Wednesday, November 2, 2011

Convenes
classes devem herdar de object ou de outras classes
que herdam de object
classes antigas (old style) no seguem essa regra
no existem mais classes antigas em Python 3
construtor deve se chamar __new__ (uso raro)
inicializador deve se chamar __init__ (uso comum)
o __init__ faz o papel do que chamamos de construtor
em outras linguagens
Wednesday, November 2, 2011

__init__ versus __new__


__init__ recebe uma instncia j construda, e sua
funo incializar os atributos da instncia
isso o mesmo que acontece em Java!
Em Python temos mais controle: podemos
sobrescrever o mtodo __new__ da classe para
interferir no processo de construo da instncia
na prtica bem raro implementarmos __new__
tcnica avanada de meta-programao
Wednesday, November 2, 2011

Instncias abertas
instncias podem receber atributos dinamicamente
por isso s vezes til criar classes vazias
no muito comum

Wednesday, November 2, 2011

Exemplo: classe vazia


>>> class Animal(object):
pass serve para
...
pass
criar blocos vazios
...
>>> baleia = Animal()
>>> baleia.nome
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Animal' object has no attribute 'nome'
>>> baleia.nome = 'Moby Dick'
>>> baleia.peso = 1200
>>> print '{0.nome} ({0.peso:.1f})'.format(baleia)
Moby Dick (1200.0)

Wednesday, November 2, 2011

Classes abertas?
Em Ruby as classes so abertas, a sintaxe comum
permite que um mdulo redefina uma classe e adicione
atributos a uma classe definida em outro mdulo
uma violao do princpio Open Closed (SOLID)
entidades de software (classes, mdulos, funes etc.)
devem ser abertas para extenso mas fechadas para
modificao (Bertrand Meyer, OO Sw. Construction)
Em Python isso chamado de monkey patching, usa
uma sintaxe de reflexo explcita e no
considerada uma boa prtica (mas acontece)
Wednesday, November 2, 2011

Atributos
de classe de instncia
>>> class Animal(object):
...
nome = 'Rex'
...
>>> cao = Animal()
>>> cao.nome
'Rex'
>>> cao.nome = 'Fido'
>>> cao.nome
'Fido'
>>> Animal.nome
'Rex'
>>> dino = Animal()
>>> dino.nome
'Rex'
Wednesday, November 2, 2011

atributo da classe
atributo encontrado
na classe
atributo criado
na instanncia
nada mudou na classe

Mtodos de classe/estticos
Indicados por decoradores de funo
class Exemplo(object):
@classmethod
def da_classe(cls, arg):
return (cls, arg)
@staticmethod
def estatico(arg):
return arg
>>> Exemplo.da_classe('fu')
(<class '__main__.Exemplo'>, 'fu')
>>> Exemplo.estatico('bar')
'bar'
Wednesday, November 2, 2011

Herana
no exemplo abaixo, ContadorTolerante extende Contador
o mtodo contar est sendo sobrescrito
os mtodos __init__ e
incluir so herdados

class Contador(object):
def __init__(self):
self.contagem = {}
def incluir(self, item):
qtd = self.contagem.get(item, 0) + 1
self.contagem[item] = qtd
def contar(self, item):
return self.contagem[item]

class ContadorTolerante(Contador):
def contar(self, item):
return self.contagem.get(item, 0)
Wednesday, November 2, 2011

Invocar mtodo de
super-classe
A forma mais simples:
class ContadorTotalizador(Contador):
def __init__(self):
Contador.__init__(self)
self.total = 0
def incluir(self, item):
Contador.incluir(self, item)
self.total += 1

Wednesday, November 2, 2011

Invocar mtodo de
super-classe
A forma mais correta:
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

Wednesday, November 2, 2011

Herana mltipla
classe que totaliza e no levanta excees:
class ContadorTT(ContadorTotalizador, ContadorTolerante):
pass

como funciona:
MRO = ordem de resoluo de mtodos
>>> ContadorTT.__mro__
(<class '__main__.ContadorTT'>,
<class '__main__.ContadorTotalizador'>,
<class '__main__.ContadorTolerante'>,
<class '__main__.Contador'>,
<type 'object'>)
Wednesday, November 2, 2011

Uso de herana mltipla


>>>
>>>
...
...
...
>>>
>>>
...
...
>>>
7
>>>
3
>>>
0

from contadores import *


class ContadorTT(ContadorTotalizador,
ContadorTolerante):
pass
ctt = ContadorTT()
for letra in 'abacaxi':
ctt.incluir(letra)
ctt.total
ctt.contar('a')
ctt.contar('z')

Wednesday, November 2, 2011

Encapsulamento
Propriedades:
encapsulamento para quem precisa de
encapsulamento
>>>
>>>
>>>
10
>>>
>>>
0

Wednesday, November 2, 2011

a = C()
a.x = 10
print a.x
a.x = -10
print a.x

violao de
encapsulamento?
pergunte-me
como!

Propriedade: implementao
apenas para leitura, via decorator:
class C(object):
def __init__(self, x):
self.__x = x
@property
def x(self):
return self.__x

a notao __x protege o atributo contra acessos


acidentais (__x = dois underscores esquerda)

Wednesday, November 2, 2011

Propriedade: implementao 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)

Wednesday, November 2, 2011

Propriedade: implementao 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

Wednesday, November 2, 2011

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

Wednesday, November 2, 2011

Polimorfismo: definio
O conceito de polimorfismo significa que podemos tratar
instncias de diferentes classes da mesma maneira.
Assim, podemos enviar uma mensagem a um objeto sem
saber de antemo 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

Wednesday, November 2, 2011

Polimorfismo
Fatiamento e len
listas e strings so sequncias
>>> l = [1, 2, 3]
>>> l[:2]
[1, 2]
>>> 'casa'[:2]
'ca'
>>> len(l)
3
>>> len('casa')
4

Wednesday, November 2, 2011

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
r
o
c
Wednesday, November 2, 2011

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
5
4
3
Wednesday, November 2, 2011

Exemplo: baralho polimrfico


comeamos com uma classe bem simples:
class Carta(object):
def __init__(self, valor, naipe):
self.valor = valor
self.naipe = naipe
def __repr__(self):
return '<%s de %s>' % (self.valor, self.naipe)

Wednesday, November 2, 2011

Baralho polimrfico 2
mtodos especiais: __len__, __getitem__`
com esses mtodos, Baralho implementa o
protocolo das sequncias imutveis
class Baralho(object):
naipes = 'paus copas espadas ouros'.split()
valores = 'A 2 3 4 5 6 7 8 9 10 J Q K'.split()
def __init__(self):
self.cartas = [Carta(v, n)
for n in self.naipes
for v in self.valores]
def __len__(self):
return len(self.cartas)
def __getitem__(self, pos):
return self.cartas[pos]
Wednesday, November 2, 2011

Baralho polimrfico 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>
<7 de ouros>
<6 de ouros>
<5 de ouros>
Wednesday, November 2, 2011

Baralho polimrfico 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>
a
mesma
carta
pode
<4 de ouros>
sair duas vezes!
<A de copas>
<5 de ouros>
<9 de paus>
>>> for i in range(5): print choice(b)
...
<3 de paus>
<9 de copas>
Wednesday, November 2, 2011

Baralho polimrfico 5
>>> from random import shuffle
Python vem com
>>> l = range(10)
pilhas includas!
>>> l
[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

ooops...

Wednesday, November 2, 2011

Baralho polimrfico 6
>>> def meu_setitem(self, pos, valor):
...
self.cartas[pos] = valor
...
>>> Baralho.__setitem__ = meu_setitem
>>> shuffle(b)
>>> b[:5]
[<J de espadas>, <Q de paus>, <2 de paus>,
<6 de paus>, <A de espadas>]
>>>

Wednesday, November 2, 2011

monkeypatch
agora
funciona!

Baralho polimrfico 7
fazendo direito (sem monkey-patch)
class Baralho(object):
naipes = 'paus copas espadas ouros'.split()
valores = 'A 2 3 4 5 6 7 8 9 10 J Q K'.split()
def __init__(self):
self.cartas = [Carta(v, n)
for n in self.naipes
for v in self.valores]
def __len__(self):
return len(self.cartas)
def __getitem__(self, pos):
return self.cartas[pos]
def __setitem__(self, pos, item):
self.cartas[pos] = item
Wednesday, November 2, 2011

Academia
Python
instrutor: Luciano Ramalho
112 horas/aula, 3 meses

!"!#$%&!'()*+,COM LUCIANO RAMALHO

5 mdulos

A Academia Python d uma viso acessvel e prtica da linguagem: principais


bibliotecas, desenvolvimento Web com Django, receitas para tarefas comuns,
!
programao Orientada
a Objetos e multi-paradigma e testes automatizados.
!

Introduo linguagem
OO e frameworks

As academias da Globalcode
so formaes completas compostas por vrios
!
mdulos com muito! mais tempo para os alunos interagirem com os instrutores.
! tem cinco mdulos totalizando 112 horas aula. fruto da
A Academia Python
!
unio entre a qualidade
e metodologia da Globalcode e a experincia e
conhecimento do Luciano Ramalho.

Mdulos da Academia Python:


PY1 - Introduo linguagem Python

Django + Jquery

PY2 - Orientao a Objetos e frameworks


PY3 - Desenvolvimento Web com Django e JQuery
PY4 - Django profissional

Django profissional
Cloud, NoSQL etc.
Wednesday, November 2, 2011

PY5 - Cloud, NoSQL e novas arquiteturas

@luciano

!"#$%&'()%*+),%-.',%/'*0
Mais informaes:

!"#$%&'()%*+),%-./,%0/*12

2!""#$%"&'())%*