Orientação A Objeto em Python
Orientação A Objeto em Python
Orientação A Objeto em Python
Orientao a Objetos
em Python (sem sotaque)
Luciano Ramalho
luciano@ramalho.org
Wednesday, November 2, 2011
Python
com
sotaque
javans
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
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
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
>>> "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
Sintaxe de classes
no usamos
this
usamos
self
cont = Contador()
palavra = 'abacaxi'
for letra in palavra:
cont.incluir(letra)
no existe o
operador new
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
Instncias abertas
instncias podem receber atributos dinamicamente
por isso s vezes til criar classes vazias
no muito comum
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
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
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
Encapsulamento
Propriedades:
encapsulamento para quem precisa de
encapsulamento
>>>
>>>
>>>
10
>>>
>>>
0
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
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)
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
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
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
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
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...
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>]
>>>
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
5 mdulos
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.
Django + Jquery
Django profissional
Cloud, NoSQL etc.
Wednesday, November 2, 2011
@luciano
!"#$%&'()%*+),%-.',%/'*0
Mais informaes:
!"#$%&'()%*+),%-./,%0/*12
2!""#$%"&'())%*