Objetos são a unidade fundamental de qualquer sistema orientado a objetos. Em Python, como introduzido na seção 2.3.2, tudo é um objeto -- tipos, valores, classes, funções, métodos e, é claro, instâncias: todos possuem atributos e métodos associados. Nesta seção serão descritas as estruturas da linguagem para suportar objetos definidos pelo programador.
Por exemplo, em um programa que manipula formas geométricas, seria possível conceber uma classe denominada Retangulo:
Um exemplo de uma implementação possível desta classe está no módulo retangulo.py a seguir:
class Retangulo:
lado_a = None
lado_b = None
def __init__(self, lado_a, lado_b):
self.lado_a = lado_a
self.lado_b = lado_b
print "Criando nova instância Retangulo"
def calcula_area(self):
return self.lado_a * self.lado_b
def calcula perímetro(self):
return 2 * self.lado_a + 2 * self.lado_b
Esta classe define os dois atributos descritos acima, e três métodos. Os três métodos definidos incluem sempre, como primeiro argumento, uma variável denominada self, que é manipulada no interior do método. Este é um ponto fundamental da sintaxe Python para métodos: o primeiro argumento é especial, e convenciona-se utilizar o nome self para ele; logo a seguir será discutido para que existe.
Dois dos métodos codificados correspondem às operações descritas inicialmente, e há um método especial incluído: __init__(). O nome deste método tem significância particular em Python: é o método construtor, um método opcional invocado quando a classe é instanciada, que é o nome dado à ação de criar objetos a partir de uma classe.
Conceitualmente, a instância possui duas propriedades fundamentais: a classe a partir da qual foi criada, que define suas propriedades e métodos padrão, e um estado, que representa o conjunto de valores das propriedades e métodos definidos naquela instância específica. A instância possui um ciclo de vida: é criada (e neste momento seu construtor é invocado), manipulada conforme necessário, e destruída quando não for mais útil para o programa. O estado da instância evolui ao longo do seu ciclo de vida: seus atributos são definidos e têm seu valor alterado através de seus métodos e de manipulação realizada por outros objetos.
O que Python chama de `instância' é freqüentemente denominado `objeto' em outras linguagens, o que cria alguma confusão uma vez que qualquer dado em Python pode ser considerado um `objeto'. Em Python, instâncias são objetos criados a partir de uma classe definida pelo programador.
Retomando o nosso exemplo acima: a partir da classe Retangulo que foi definida, poderíamos instanciar objetos retângulo específicos: um com lados de comprimento 1 e 2, e outro com lados de comprimento 2 e 3:
>>> from retangulo import Retangulo
>>> r1 = Retangulo(1, 2)
Criando nova instância Retângulo
>>> r2 = Retangulo(2, 3)
Criando nova instância Retângulo
Observe que ao instanciar o retângulo:
def __init__(self, lado_a, lado_b):
self.lado_a = lado_a
self.lado_b = lado_b
print "Criando nova instância Retangulo"
Aqui cabe uma pausa para revelar o propósito da variável self, definida como primeiro argumento dos métodos. Esta variável representa a instância sobre a qual aquele método foi invocado. Esta propriedade é de importância fundamental para OO em Python, porque através desta variável é que atributos e métodos desta instância podem ser manipulados no código dos seus métodos.
Continuando com a análise do bloco de código acima:
Uma vez instanciados os retângulos, podemos acessar seus métodos. De maneira idêntica aos métodos da lista apresentados na seção 2.3.2, a sintaxe utiliza um ponto seguido do nome do método acompanhado de parênteses:
>>> print r1.calcula_area()
2
>>> print r2.calcula_perimetro()
10
Conforme esperado, as funções retornaram os valores apropriados para cada instância. Fazendo mais uma demonstração do uso do argumento self, vamos observar o código de um dos métodos:
def calcula_area(self):
return self.lado_a * self.lado_b
O onipresente argumento self aqui é utilizado como meio de acesso aos atributos lado_a e lado_b. Este código permite visualizar o funcionamento pleno deste mecanismo: ao ser invocado o método calcula_area sobre a instância r1, o argumento self assume como valor esta mesma instância; portanto, acessar atributos de self internamente ao método equivale, na prática, a acessar atributos de r1 externamente.
Em Python é possível, inclusive, acessar os atributos da instância diretamente, sem a necessidade de usar um método:
>>> print r1.lado_a
1
>>> print r1.lado_b
2
Os valores, logicamente, correspondem aos inicialmente fornecidos à instância por meio do seu construtor.
Algumas linguagens permitem restringir acesso aos atributos de uma instância, oferecendo o conceito de variável privada. Python não possui uma construção sintática literalmente equivalente, mas existem duas formas de indicar que um atributo não deve ser acessado externamente: