Orientação a objetos em Python, o básico

python_oop1

Pois é, depois de tratar deste assunto em Perl, PHP, Ruby e até mesmo em assembly de Z80, dei conta de que Python ficou de fora e como, indiretamente, há alguma relação com o projeto em Bottle achei que seria interessante escrever um pouco o assunto antes de seguir adiante.

Então, o mínimo necessário em Python para se trabalhar com objetos é o seguinte…

Criando uma classe

Você pode criar as classes dentro do mesmo arquivo do programa ou importá-la de um arquivo externo/ diretório — o que é recomendável pois acaba já que facilita o reuso. A sintaxe é esta aqui:

class «Nome da Classe»(object):
    ...

Apenas (re)lembrando que o Python não se utiliza elementos de sintaxe para delimitar os blocos de código — algo como “{ … }“, “do … end“, “begin … end” etc — e a delimitação é feita através da própria indentação, neste caso tudo aquilo que está 4 espaços mais a direita do comando class é considerado parte da classe.

Para manter a sanidade, configure o editor de textos para tratar tabulações como espaços e utilize espaçamentos regulares e múltiplos de um mesmo valor — geralmente se recomenda uma tabulação em múltiplos de quatro.

Mantendo a coerência com os guias anteriores a famosa classe Nome:

class Nome(object):
    pass

O comando pass faz coisa alguma e só está aí para manter a classe sintaticamente válida e a este arquivo darei o nome de “nomes.py”.

Construtor

O construtor é chamado de __init__:

class «Nome da Classe»(object):
    ...
    def __init__( self, «parâmetros» ):
        ...

No código de exemplo ele ficaria assim:

class Nome(object):
    def __init__( self, nome, sobrenome ):
        self.nome=nome
        self.sobrenome=sobrenome

Assim como em Perl, em Python você também precisa passar o objeto (o tal do self) nos parâmetros que o método está recebendo.

Criando outros métodos

Os demais métodos da classe ficariam assim:

    ...
    def escreve_nome(self):
        return self.nome
    
    def escreve_nome_completo(self):
        return self.nome+" "+self.sobrenome
    ...

E, tal qual aconteceu no exemplo em Ruby, em Python há a recomendação de se usar um método específico para exibir o conteúdo do objeto como uma string, ele se chama __str__.

Então o escreve_nome() vira:

    ...
    def __str__(self):
        return self.nome
    ...

Por seguir as “regras da linguagem” você (ou qualquer outra pessoa) sabe que basta usar print para retornar o conteúdo do objeto sem o risco de receber um  na tela. 🙂

Testando

Um programa (muito) simples, o “nome.py” e com a única função de testar a classe:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from nomes import Nome

giovanni=Nome("Giovanni","Nunes")

print("O primeiro nome é {}.".format(giovanni))

print("E {} o nome completo.".format(giovanni.escreve_nome_completo()))

exit

O resultado será algo assim:

$ ./testa-nome.py 
O primeiro nome é Giovanni.
E Giovanni Nunes o nome completo.

Mais abaixo há uma explicação sobre o from nomes import Nome usado para trazer a classe para dentro do programa.

Herança

Relembrando que a definição da classe foi feita com def Nome(object) e isto pode ser lido como a nova classe “Nome” herda as definições da classe (primitiva) “object”. Assim, tendo esta mesma lógica em mente, para criar uma nova classe herdando os atributos e métodos de “Nome” ficaria:

class Nome(object):
     ...

class Supernome(Nome):
    def escreve_nome_completo(self):     
        return self.sobrenome.upper()+", "+self.nome

No exemplo estou usando a estrutura já existente para a classe “Nome” para criar a “Supernome” porém alterando um de seus métodos (o “escreve_nome_completo”) para produzir um resultado diferente.

Basta alterar o programa de exemplo para testá-la:

#!/usr/bin/env python3
...
from nomes import Supernome
...
giovanni=Supernome("Giovanni","Nunes")
...
exit

Para obter o resultado:

./testa-nome.py 
O primeiro nome é Giovanni.
E NUNES, Giovanni o nome completo.

Já falei que  o programa de testes é simples? 🙂

Sobre ‘from’ e ‘import’

A primeira vista o comando import do Python parece ser igual ao include()* do PHP ou o require do Ruby mas ele acaba fazendo bem mais do que simplesmente colar um arquivo externo dentro do seu programa. Nele é possível selecionar as partes do tal arquivo externo (ou módulo) que você deseja trazer para dentro do seu programa.

Por exemplo, a inclusão das duas classes no programa de exemplo foi feita assim:

...
from nomes import Nome
...

ou então:

...
from nomes import Supernome
...

E em ambos os casos somente as classes Nome ou Supernome foram respectivamente carregadas. E é possível demonstrar da seguinte maneira:

$ python3
Python 3.5.2 (default, Nov 17 2016, 17:05:23) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from nomes import Supernome
>>> giovanni=Nome("Giovanni","Nunes")
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'Nome' is not defined
>>> _

Ou seja, somente a classe Supernome foi carregada e não Nome — apesar de toda a “coisa” da herança. E para carregar ambas as classes bastaria fazer:

from nomes import Nome, Sobrenome

Ou então:

import nomes

Mas aqui há uma diferença, deste jeito o import se comportará tal qual seus análogos include e require pois importará Nome, Supernome e tudo mais que estiver definido dentro do arquivo “nomes.py” independente de ser ou não usado pelo programa.

E como “chatice” adicional você terá de lidar com tudo dentro do seu próprio escopo:

...
giovanni=nomes.Nome("Giovanni","Nunes")
...

Mas isto é suportável. 🙂

(*) Claro, no caso do PHP há tanto a função include() quanto a require() só que ambas fazem (e são) a  mesma coisa.

Finalizando

Em Python não existe a figura de atributos e métodos de uso privado, você pode até assinalá-los como tal ao utilizar o prefixo “__” nos nomes mas isto serve mais como uma informação ao programador do que ao interpretador.

Querendo saber um pouco mais sobre o assunto recomendo a leitura do An Introduction to Classes and Inheritance (in Python) e, para finalizar, fica a sugestão “de sempre” de recriar os demais métodos lá do exemplo de Perl. 🙂

Anúncios

3 comentários sobre “Orientação a objetos em Python, o básico

  1. Pingback: Orientação a objetos em Python, o básico - Linux em Ação XYZ

  2. Pingback: Orientação a objetos em JavaScript, o básico | giovannireisnunes

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s