Classes introduzem novidades sintáticas, três novos tipos de objetos, e também semântica nova.
9.3.1
Sintaxe de Definição de Classe
A forma mais simples de definir uma classe é:
class NomeDaClasse: <comando-1> . . . <comando-N>
Definições de classes, como definições de funções (comandos def) devem ser executados antes que tenham qualquer efeito. Você pode colocar uma definição de classe após um teste condicional ifou dentro de uma função.
Na prática, os comandos dentro de uma classe serão definições de funções, mas existem outros comandos que são permitidos. Definições de função dentro da classe possuem um lista peculiar de argumentos determinada pela convenção de chamada a métodos.
Quando se fornece uma definição de classe, um novo espaço de nomes é criado. Todas atribuições de variáveis são vinculadas a este escopo local. Em particular, definições de função também são armazenadas neste escopo. Quando termina o processamento de uma definição de classe (normalmente, sem erros), um objeto de classe é criado. Este objeto encapsula o conteúdo do espaço de nomes criado pela definição da classe. O escopo local ativo antes da definição da classe é restaurado, e o objeto classe é vinculado a este escopo com o nome dado a classe.
9.3.2
Objetos de Classe
Objetos de Classe suportam dois tipos de operações: referências a atributos e instanciação.
Referências a atributos de classe utilizam a sintaxe padrão utilizada para quaisquer referências a atributos em Python: obj.name. Atributos válidos são todos os nomes presentes no espaço de nomes da classe quando o objeto classe foi criado. Portanto, se a definição da classe era:
class MyClass:
"Um exemplo simples de classe" i = 12345
def f(self):
return ’hello world’
entãoMyClass.ieMyClass.fsão referências a atributos válidos, retornando um inteiro e um objeto função, respectivamente. Atributos de classe podem receber atribuições, logo você pode mudar o valor deMyClass.i por atribuição. __doc__ é também um atributo válido, que retorna a docstring pertencente a classe: "Um exemplo simples de classe".
Instanciação de Classe também utiliza uma notação de função. Apenas finja que o objeto classe não possui parâmetros e retorna uma nova instância da classe. Por exemplo:
x = MyClass()
pela classe,__init__(), veja:
def __init__(self): self.data = []
Quando uma classe define um método__init__(), o processo de instânciação automáticamente invoca__- init__()sobre a recém-criada instância de classe. Neste exemplo, uma nova intância já inicializada pode ser obtida por:
x = MyClass()
Naturalmente, o método __init__()pode ter argumentos para aumentar sua flexibilidade. Neste caso, os argumentos passados para a instanciação de classe serão delegados para o método__init__(). Como ilustrado em:
>>> class Complex:
... def __init__(self, realpart, imagpart):
... self.r = realpart ... self.i = imagpart ... >>> x = Complex(3.0, -4.5) >>> x.r, x.i (3.0, -4.5)
9.3.3
Instâncias
Agora, o que podemos fazer com instâncias ? As únicas operações reconhecidas por instâncias são referências a atributos. Existem dois tipos de nomes de atributos válidos: atributos de dados e métodos.
Atributos-de-dados, que correspondem a “variáveis de instância” em Smalltalk, e a “membros” em C++. Atributos-de-dados não não precisam ser declarados. Assim como variáveis locais, eles passam a existir na primeira vez em que é feita uma atribuição. Por exemplo, sexé uma instância deMyClasscriada acima, o próximo trecho de código irá imprimir o valor16, sem deixar rastro (por causa dodel):
x.counter = 1
while x.counter < 10:
x.counter = x.counter * 2 print x.counter
del x.counter
O outro tipo de referências a atributos são métodos. Um método é uma função que “pertence a” uma instância (em Python, o termo método não é aplicado exclusivamente a instâncias de classes definidas pelo usuário: outros tipos de objetos também podem ter métodos; por exemplo, objetos listas possuem os métodos: append, insert, remove, sort, etc).
Nomes de métodos válidos de uma instância dependem de sua classe. Por definição, todos atributos de uma classe que são funções equivalem a um método presente nas instâncias. No nosso exemplo,x.fé uma referência de método válida já queMyClass.fé uma função, enquantox.inão é, já queMyClass.inão é função. Entretanto,x.fnão é o mesmo queMyClass.f— o primeiro é um método de objeto , o segundo é um objeto função.
9.3.4
Métodos de Objeto
Normalmente, um método é chamado imediatamente:
x.f()
No exemplo comMyClasso resultado será a string’hello world’. No entanto, não é obrigatótio chamar o método imediatamente: comox.fé também um objeto (tipo método), ele pode ser armazenado e invocado a posteriori. Por exemplo:
xf = x.f while True:
print xf()
continuará imprimindo ‘hello world’ até o final dos tempos.
O que ocorre precisamente quando um método é chamado ? Você deve ter notado que x.f() foi chamado sem nenhum parâmetro, porém a definição da funçãof especificava um argumento. O que aconteceu com o argumento ? Certamente Python levantaria uma exceção se o argumento estivesse faltando...
Talvez você já tenha advinhado a resposta: o que há de especial em métodos é que o objeto (a qual o método pertence) é passado como o primeiro argumento da função. No nosso exemplo, a chamadax.f()é exatamente equivalente aMyClass.f(x). Em geral, chamar um método com uma lista de n argumentos é equivalente a chamar a função na classe correspondente passando a instância como o primeiro argumento antes dos demais argumentos.
Se você ainda não entendeu como métodos funcionam, talvez uma olhadela na implementação sirva para clarear as coisas. Quando um atributo de instância é referenciado e não é um atributo de dado, a sua classe é procurada. Se o nome indica um atributo de classe válido que seja um objeto função, um objeto método é criado pela composição da instância alvo e do objeto função. Quando o método é chamado com uma lista de argumentos, ele é desempa- cotado, uma nova lista de argumentos é criada a partir da instância original e da lista original de argumentos do método. Finalmente, a função é chamada com a nova lista de argumentos.