Introduo
Orientao a Objetos
em Python (sem sotaque)
Luciano Ramalho
luciano@[Link]
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):
[Link] = {}
def incluir(this, item):
qtd = [Link](item, 0) + 1
[Link][item] = qtd
def contar(this, item):
return [Link][item]
Wednesday, November 2, 2011
Classe com 3 mtodos
class Contador(object):
def __init__(this):
[Link] = {}
no usamos
this
def incluir(this, item):
qtd = [Link](item, 0) + 1
[Link][item] = qtd
def contar(this, item):
return [Link][item]
Wednesday, November 2, 2011
Classe com 3 mtodos
class Contador(object):
def __init__(self):
[Link] = {}
usamos
self
def incluir(self, item):
qtd = [Link](item, 0) + 1
[Link][item] = qtd
def contar(self, item):
return [Link][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):
[Link] = {}
def incluir(self, item):
qtd = [Link](item, 0) + 1
[Link][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:
[Link](letra)
no existe o
operador new
for letra in sorted(set(pal)):
print letra, [Link](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()
>>> [Link]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Animal' object has no attribute 'nome'
>>> [Link] = 'Moby Dick'
>>> [Link] = 1200
>>> print '{[Link]} ({[Link]:.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()
>>> [Link]
'Rex'
>>> [Link] = 'Fido'
>>> [Link]
'Fido'
>>> [Link]
'Rex'
>>> dino = Animal()
>>> [Link]
'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')
>>> [Link]('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):
[Link] = {}
def incluir(self, item):
qtd = [Link](item, 0) + 1
[Link][item] = qtd
def contar(self, item):
return [Link][item]
class ContadorTolerante(Contador):
def contar(self, item):
return [Link](item, 0)
Wednesday, November 2, 2011
Invocar mtodo de
super-classe
A forma mais simples:
class ContadorTotalizador(Contador):
def __init__(self):
Contador.__init__(self)
[Link] = 0
def incluir(self, item):
[Link](self, item)
[Link] += 1
Wednesday, November 2, 2011
Invocar mtodo de
super-classe
A forma mais correta:
class ContadorTotalizador(Contador):
def __init__(self):
super(ContadorTotalizador, self).__init__()
[Link] = 0
def incluir(self, item):
super(ContadorTotalizador, self).incluir(item)
[Link] += 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':
[Link](letra)
[Link]
[Link]('a')
[Link]('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
@[Link]
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):
[Link] = valor
[Link] = naipe
def __repr__(self):
return '<%s de %s>' % ([Link], [Link])
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):
[Link] = [Carta(v, n)
for n in [Link]
for v in [Link]]
def __len__(self):
return len([Link])
def __getitem__(self, pos):
return [Link][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/[Link]/
Versions/2.6/lib/python2.6/[Link]", 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):
...
[Link][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):
[Link] = [Carta(v, n)
for n in [Link]
for v in [Link]]
def __len__(self):
return len([Link])
def __getitem__(self, pos):
return [Link][pos]
def __setitem__(self, pos, item):
[Link][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!""#$%"&'())%*