Sei sulla pagina 1di 33

Claudio Esperana

Python:
Python:
Classes
Classes
Orientao a Objetos
Orientao a Objetos

uma disciplina de programao assim como a


Programao Estruturada

Tenta unificar as idias de algoritmos e estruturas de


dados atravs do conceito de Objeto

Um objeto uma unidade de software que encapsula


algoritmos e os dados sobre o qual os algoritmos atuam

Os seguintes conceitos so importantes quando falamos


de orientao a objetos:

Polimorfismo

Abstrao

Herana
Polimorfismo
Polimorfismo

o que permite que dois objetos diferentes possam ser


usados de forma semelhante

Por exemplo, tanto listas quanto tuplas ou strings podem ser


indexadas por um nmero entre colchetes e suportam o
mtodo len

Assim, se escrevemos ...


for i in range(len(X)): print i, X[i]

...no possvel saber de antemo se X uma tupla, uma


lista ou uma string

Desta forma, se escrevemos um algoritmo para ser


aplicado um objeto X, ento tambm pode ser aplicado a
um objeto Y desde que Y seja suficientemente polimrfico
a X
Abstrao (ou encapsulamento)
Abstrao (ou encapsulamento)

o que permite que um objeto seja utilizado sabendo-se


sobre ele apenas a sua interface

Em particular, no precisamos conhecer a implementao


dos seus mtodos

Em OO a abstrao tem mais alcance pois um objeto


encapsula tanto dados como algoritmos

Assim, podemos atribuir objetos ou passar objetos como


argumentos, sem necessariamente saber como o objeto est
implementado
Herana
Herana

o que permite construir objetos que so especializaes


de outro objeto

Isso permite o reuso de software j que objetos


especializados herdam dos objetos genricos uma srie de
atributos comuns

Por exemplo, considere um objeto que representa uma


forma geomtrica. Ento, ele pode ter caractersticas tais
como rea, permetro, centride, etc.

Um polgono uma forma geomtrica,

Portanto, herda todas as caractersticas de formas geomtricas

Deve suportar tambm caractersticas especficas como


nmero de lados e comprimento de arestas
Objetos em Python
Objetos em Python

Python suporta OO atravs de classes

Uma classe pode ser entendida como uma fbrica de


objetos, todos com as mesmas caractersticas

Diz-se que objeto fabricado por uma classe uma instncia


da classe

A rigor, uma classe tambm um objeto

Encapsula dados e algoritmos

Entretanto, no normalmente um objeto fabricado por uma


classe, mas um objeto criado pela construo class

Um objeto encapsula dados e algoritmos sob a forma de


variveis e mtodos

comum chamar esses elementos constituintes dos objetos


de atributos
Declarao de uma classe
Declarao de uma classe

A maneira mais simples :


class nome:
var = valor
...
var = valor
def metodo (self, ... arg):
...
def metodo (self, ... arg):
...

As variveis e os mtodos so escritos precedidos pelo


nome da classe e por um ponto (.)

Assim, uma variavel v definida numa classe c escrita c.v

Os mtodos sempre tm self como primeiro argumento

self se refere a uma instncia da classe

Uma nova instncia da classe criada usando nome ()


!emplo
!emplo
>>> class C:
a = 2
b = 3
def f(self,x):
return C.ax!C.b
>>> C.a = "
"
>>> C.b
3
>>> ob#=C()
>>> ob#.f($)
%$
Atributos de inst"ncias
Atributos de inst"ncias

No exemplo anterior, a e b eram atributos da classe C e


portanto usveis por qualquer instncia de C

Mais freqentemente, precisamos de atributos associados


a instncias individuais

Um atributo attr associado a uma instncia ob# tem


nome ob#.attr

Se queremos nos referir a um atributo attr de um objeto


dentro de algum de seus mtodos, usamos o nome
self.attr
!emplo
!emplo
>>> class C:
def init(self,a=2,b=3):
self.a = a
self.b = b
def f(self,x):
return self.ax!self.b
>>> ob#% = C()
>>> ob#%.init(2,3)
>>> ob#2 = C()
>>> ob#2.init(&,%)
>>> ob#%.f($)
%$
>>> ob#2.f($)
'$
Atributos herdados da classe
Atributos herdados da classe

Se uma classe define atributos de classe, as instncias


herdam esses atributos da classe como atributos de
instncia

Ex.:
>>> class C:
a = %
def f(self,x):
self.a != x
>>> c = C()
>>> c.f(2)
>>> c.a
3
>>> C.a
%
Construtores
Construtores

Um mtodo como init do exemplo anterior bastante til


para inicializar atributos da instncia e conhecido como
construtor da classe

Na verdade, Python suporta construtores que podem ser


chamados automaticamente na criao de instncias

Basta definir na classe um mtodo chamado ((init((

Este mtodo chamado automaticamente durante a criao


de um nova instncia da classe, sendo que os argumentos
so passados entre parnteses aps o nome da classe

Obs.: o mtodo ((init(( apenas um exemplo de


mtodo mgico que invocado de maneira no padro
(veremos outros adiante)
!emplo
!emplo
>>> class C:
def ((init(((self,a=2,b=3):
self.a = a
self.b = b
def f(self,x):
return self.ax!self.b

>>> ob#% = C()
>>> ob#2 = C(&,%)
>>> ob#%.f($)
%$
>>> ob#2.f($)
'$
speciali#ao de classes
speciali#ao de classes

Para fazer uma classe C herdar de outra B, basta declarar C


como:
class C(B):
. . .

Diz-se que C sub-classe (ou derivada) de B ou que B super-


classe (ou base) de C

C herda todos os atributos de B

A especializao de C se d acrescentando-se novos atributos


(variveis e mtodos) ou alterando-se mtodos

Se, um mtodo de C, precisa invocar um mtodo m de B, pode-


se utilizar a notao B.m para diferenciar do m de C, referido
como C.m
!emplo
!emplo
>>> class ):
n = 2
def f(self,x): return ).nx
>>> class C()):
def f(self,x): return ).f(self,x)2
def g(self,x): return self.f(x)!%
>>> b = )()
>>> c = C()
>>> b.f(3)
*
>>> c.f(3)
3*
>>> c.g(3)
3$
>>> ).n = '
>>> c.f(3)
22'

$nbound %ethod
$nbound %ethod

O parmetro self no pode ser removido da chamada da


funo f de B, na classe C, do exemplo anterior:
>>> class C()):
def f(self,x): return ).f(x)2
def g(self,x): return self.f(x)!%
>>> c=C()
>>> print c.f(3)
+racebac, (-ost recent call last):
.ile /0stdin>/, line %, in 0-odule>
.ile /0stdin>/, line 2, in f
+1pe2rror: unbound -et3od f() -ust be called 4it3 ) instance
as first argu-ent (got int instance instead)
Construtores de classes deri&adas
Construtores de classes deri&adas

O construtor de uma classe D derivada de C precisa


chamar o construtor de C

A chamada do construtor de C no feita por default

Permite inicializar os elementos de C que no so


especficos de D

Usa-se a notao C.__init__(self, ...)


Construtores de classes deri&adas
Construtores de classes deri&adas

Exemplo:
>>> class C:
... def ((init(((self):
... print /Construtor de C/
... self.x = %
...
>>> class 5(C):
... def ((init(((self):
... print /Construtor de 5/
... C.((init(((self)
... self.1 = 2
...
>>> d=5()
Construtor de 5
Construtor de C
>>> d.x
%
>>> d.1
2
Classes no 'no&o estilo(
Classes no 'no&o estilo(

A partir do Python 2.2, classes podem tambm ser


declaradas no chamado novo estilo:

Se uma classe no derivada de nenhuma outra, ela deve


ser declarada como derivada da classe especial chamada
object. Ex.:
class C(ob#ect):

H vrias diferenas entre o comportamento das classes


no novo estilo e as do velho estilo

Permite derivar tipos primitivos

Descritores para propriedades, mtodos estticos, mtodos


de classe, etc

Essas diferenas so pouco significativas para o iniciante


Herana m)ltipla
Herana m)ltipla

possvel construir uma classe que herda de duas ou


mais outras. Ex.:

class C(6,)): ...

Nesse caso, a classe derivada herda todos os atributos de


ambas as classes-base

Se ambas as classes base possuem um atributo com


mesmo nome, aquela citada primeiro prevalece

No exemplo acima, se 6 e ) possuem um atributo x, ento


C.x se refere ao que foi herdado de 6
!emplo
!emplo
>>> class C:
def ((init(((self,a,b):
self.a, self.b = a,b
def f(self,x):
return self.ax!self.b
>>> class 5:
def ((init(((self,legenda):
self.legenda = legenda
def escre7e(self,7alor):
print self.legenda,8=8,7alor
>>> class 2(C,5):
def ((init(((self,legenda,a,b):
C.((init(((self,a,b)
5.((init(((self,legenda)
def escre7e(self,x):
5.escre7e(self,self.f(x))
>>> e = 2(/f/,%9,3)
>>> e.escre7e(:)
f = :3
Atributos pri&ados
Atributos pri&ados

Em princpio, todos os atributos de um objeto podem ser


acessados tanto dentro de mtodos da classe como de fora

Quando um determinado atributo deve ser acessado


apenas para implementao da classe, ele no deveria ser
acessvel de fora

Em princpio tais atributos no fazem parte da interface


pblica da classe

Atributos assim so ditos privados

Em Python, atributos privados tm nomes iniciados por


dois caracteres trao-embaixo, isto , __
!emplo
!emplo
>>> class C:
def ((init(((self,x): self.((x = x
def incr(self): self.((x != %
def x(self): return self.((x
>>> a = C(')
>>> a.x()
'
>>> a.incr()
>>> a.x()
*
>>> a.((x
+racebac, (-ost recent call last):
.ile /0p1s3ell;%3>/, line %, in <tople7el<
a.((x
6ttribute2rror: C instance 3as no attribute 8((x8
%*todos m+,icos
%*todos m+,icos

So mtodos que so invocados usando operadores sobre


o objeto ao invs de por nome

J vimos um mtodo desses: o construtor __init__

Alguns outros so:

Adio: ((add((

Chamado usando '!'

Subtrao: ((sub((

Chamado usando '<'

Representao: ((repr((

Chamado quando objeto impresso

Converso para string: ((str((

Chamado quando o objeto argumento do construtor da


classe str

Se no especificado, a funo __repr__ usada


!emplo
!emplo
>>> class 7etor:
def ((init(((self,x,1):
self.x, self.1 = x,1
def ((add(((self,7):
return 7etor(self.x!7.x, self.1!7.1)
def ((sub(((self,7):
return 7etor(self.x<7.x, self.1<7.1)
def ((repr(((self):
return /7etor(/!str(self.x)!/,/!str(self.1)!/)/
>>> a=7etor(%,2)
>>> a != 7etor(3,')
>>> a<7etor(2,2)
7etor(2,')
>>> print a
7etor(:,$)
Protocolos
Protocolos

Diferentemente de outras linguagens, no h necessidade


de classes serem relacionadas para haver polimorfismo
entre elas, basta que implementem mtodos semelhantes

Um protocolo uma especificao de polimorfismo


informal

Por exemplo, listas, strings e tuplas possuem em comum o


fato de poderem iterar sobre uma coleo de elementos

Todas implementam o protocolo para seqncias

Mtodos mgicos para indexar, alterar, etc.


Protocolo para se-./ncias
Protocolo para se-./ncias

((len(((self) retorna o comprimento da seqncia

Chamada: len(objeto)

((getite-(((self,,e1) retorna o elemento na


posio key da seqncia

Chamada: objeto[,e1]

Deve-se implementar tambm chaves negativas!

((setite-(((self,,e1,7alue)

Chamada: objeto[,e1]=7alue

Apenas para seqncias mutveis

((del(((self,,e1)

Chamada por del objeto[,e1]

Apenas para (algumas) seqncias mutveis


!emplo
!emplo
>>> class =rogressao6rit-etica:
def ((init(((self,a%,incr):
self.a%,self.incr=a%,incr
def ((getite-(((self,,e1):
if not isinstance(,e1,(int,long)):
raise +1pe2rror
if ,e10=9: raise >ndex2rror
return self.a%!(,e1<%)self.incr
def so-a(self,n):
return (self[%]!self[n])n?2
>>> pa = =rogressao6rit-etica(%,2)
>>> pa[%]
%
>>> pa[%9]
%"
>>> pa.so-a(%99)
%9999
Atributos0 1etters e 2etters
Atributos0 1etters e 2etters

Muitas vezes queremos que determinados atributos


possam ser acessados de forma controlada, isto , vigiados
por mtodos

Os mtodos que controlam o acesso a tais atributos so


conhecidos como getters e setters , referindo-se a mtodos
de leitura e escrita, respectivamente

Os atributos controlados so chamados de propriedades

Na verdade, podemos ter propriedades abstratas que no


correspondem 1 para 1 com atributos da classe
!emplo
!emplo
>>> class @etangulo:
def ((init(((self,ta-an3o):
self.set+a-an3o(ta-an3o)
def set+a-an3o(self,ta-an3o):
if -in(ta-an3o)09: raise Aalue2rror
self.((ta-x,self.((ta-1 = ta-an3o
def get+a-an3o(self):
return (self.((ta-x,self.((ta-1)
>>> r = @etangulo((29,39))
>>> r.get+a-an3o()
(29, 39)
>>> r.set+a-an3o((<%,9))
+racebac, (-ost recent call last):
...
Aalue2rror
A funo
A funo
property
property

A funo property pode ser usada para consubstanciar


uma propriedade implementada por mtodos de tal
maneira que ela parea um atributo da classe

Ela usada no corpo de uma declarao de classe com a


forma:
atributo = propert1(fget, fset, fdel, doc)

...onde

fget, fset, fdel so mtodos para ler, escrever e remover o


atributo

doc uma docstring para o atributo


!emplo
!emplo
>>> class @etangulo:
def ((init(((self,ta-an3o):
self.set+a-an3o(ta-an3o)
def set+a-an3o(self,ta-an3o):
if -in(ta-an3o)09: raise Aalue2rror
self.((ta-x,self.((ta-1 = ta-an3o
def get+a-an3o(self):
return (self.((ta-x,self.((ta-1)
ta-an3o = propert1(get+a-an3o,set+a-an3o)
>>> r = @etangulo((29,39))
>>> r.ta-an3o
(29, 39)
>>> r.ta-an3o = (39,39)
>>> r.ta-an3o
(39, 39)
Dicas para uso de OO
Dicas para uso de OO

Agrupe funes e dados que se referem a um mesmo problema

Por exemplo, se uma funo manipula uma varivel global,


melhor que ambas sejam definidas numa classe como
atributo e mtodo

No permita promiscuidade entre classes e instncias de classe

Por exemplo, se h necessidade de um objeto manipular um


atributo de outro, escreva um mtodo com essa
manipulao e chame-o

No escreva mtodos extensos

Em geral, um mtodo deve ser o mais simples possvel