Programação Orientada a Objetos em Python: Fácil, Útil e do seu Jeito!
- Nicholas Arand

- 9 de mai.
- 7 min de leitura
Atualizado: 30 de mai.

Aprender a programar em python é muito mais fácil do que parece, por isso, hoje vamos falar sobre algo que parece complicado, mas que você certamente já usa sem nem perceber: a Programação Orientada a Objetos (POO).
Se você já escreveu algumas linhas de código em Python, acredite ou não, mas já está usando objetos. Veja só: quando você cria um número inteiro como idade = 25, está trabalhando com um objeto do tipo int. Quando escreve um texto como nome = "Maria", está usando um objeto do tipo str.
Até mesmo quando define uma função com def dizer_oi(): está criando um objeto do tipo function. Python é uma linguagem completamente baseada em objetos - tudo nela é um objeto! Legal, né? Você já era um programador orientado a objetos e nem sabia disso!
Para ilustrar tudo isso vamos fazer alguns testes usando estes objetos:
# Criando os objetos: idade = 25 nome = 'Maria' def dizer_oi(): print('Oi') # Verificar que tipo de objeto são estes que criamos: print(type(idade)) print(type(nome)) print(type(dizer_oi))
<class 'int'> <class 'str'> <class 'function'>
Note que quando pedimos o "print" do tipo de objeto que criamos, o python nos responde que se tratam de objetos que pertencem a uma classe "class" específica. Mesmo que a gente não tenha o hábito de chamar nossas variáveis e funções de objetos, eles não deixam de ser um.
São o que chamamos de objetos "built-in" do python, um tipo especial de objetos que já vêm definidos sem que a gente precise fazê-lo, mas funcionam de maneira muito parecida com o que vemos a seguir. Mas, afinal, o que são esses objetos? Vamos entender alguns conceitos básicos.
Objetos são unidades que contêm dados ou características (chamados de atributos) e ações ou "responsabilidade" (chamadas de métodos). Eles são definidos por Classes.
Classes são como "formas" ou "desenho técnico" que definem o objeto. Quando criamos um objeto a partir de uma classe, dizemos que estamos criando uma instância daquela classe. Por exemplo, se Pessoa é uma classe, joao = Pessoa() cria uma instância chamada joao da classe Pessoa. Os atributos são as características do objeto (como joao.idade = 25) e os métodos são as funções que o objeto pode executar (como joao.seja_educado()). Simples assim! Então vamos ver na prática:
# Primeiro definimos uma classe chamada "Pessoa" class Pessoa: # Note que, por convenção, as classes têm a inicia em maiúsculo def init(self, nome: str, idade: int): # Outra convenção esquisita é que para poder criar um objeto, a classe precisa ter este método "__init__", # que, basicamente, inicializa o objeto. O "self" é outra convenção da definição de classes, que dizer # que os atributos ou métodos definidos vão se aplicar sobre o objeto em si.
self.idade = idade # Aqui criamos a idade como um atributo do self, ou seja, objeto a ser criado pela classe self.nome = nome # Aqui criamos o nome como um atributo do self, ou seja, objeto a ser criado pela classe def ser_educado(self): # Assim se criam os métodos, ou ações que podem ser tomadas sobre ou pelo objeto.
# Note que, como o método é chamado pelo objeto, ele já tem acesso aos atributos do objeto, como "self.nome" # e "self.idade" return f"Olá, bom dia! Meu nome é {self.nome} e tenho {self.idade} anos." # Aqui, o método retorna uma string com # Aqui criamos um objeto da classe "Pessoa", ou seja, um objeto do tipo "Pessoa" joao = Pessoa(nome="João", idade=25) # Note que não passamos o 'self' para a criação do objeto, pois ele já é criado # automaticamente pelo Python. O 'self' é passado automaticamente para o método "__init__" da classe.
# Note que não precisamos ser tão formais na criação dos objetos: maria = Pessoa("Maria", 30) # Já que nossas "Pessoas" são educadas por definição, chamamos o método "ser_educado" de cada uma delas, # que retorna uma saudação com o nome e idade do objeto print(joao.ser_educado()) print(maria.ser_educado())
Olá, bom dia! Meu nome é João e tenho 25 anos. Olá, bom dia! Meu nome é Maria e tenho 30 anos.
Para entender melhor ainda, podemos comparar objetos em Python com objetos do nosso dia a dia. Pense em um cubo mágico
O cubo mágico tem atributos como tamanho (2x2, 3x3), o estado atual (resolvido ou não), quantos movimentos já foram feitos, etc. E também tem métodos, sendo as ações que podemos fazer com ele: girar a face superior no sentido horário, girar a face direita no sentido anti-horário, embaralhar o cubo, etc.
Se fôssemos criar uma classe em Python para representar esse cubo, poderíamos ter algo como class CuboMagico: e depois criar uma instância com meu_cubo = CuboMagico(). Daí poderíamos acessar ou modificar seus atributos com meu_cubo.esta_resolvido, ou chamar métodos como meu_cubo.girar_face_superior(). Consegue visualizar?
Vamos a um exemplo prático:
# Primeiro definir a classe com os atributos e métodos exemplificados acima: class CuboMagico: def init(self, tamanho): self.tamanho = (tamanho,tamanho) self.esta_resolvido = False self.movimentos = 0 self.estado = self.estado_inicial() def estado_inicial(self): # função que inicializa o estado inicial de cada peça do cubo conforme seu tamanho estado = [] # Não precisamos fazer isso aqui ;) return estado def girar_face_superior(self): # Implementação do método girar_face_superior self.movimentos += 1 print(f"Girei a face superior. Já executamos {self.movimentos} movimento(s)") meu_cubo = CuboMagico(3) # Criando um cubo 3x3 # Note que mesmo que o único argumento para a criação do cubo seja a sua dimensão, criamos atributos iniciais como # o estado inicial "não resolvido" e a contagem de movimentos = 0.abs print("Tamanho:",meu_cubo.tamanho) # 3 print("Está resolvido?", meu_cubo.esta_resolvido) # False print("Quanto movimentos?", meu_cubo.movimentos) # 0 # Agora podemos executar um movimento, por exemplo, girar a face superior: meu_cubo.girar_face_superior() # E verificar o estado atual do cubo: print("Tamanho:",meu_cubo.tamanho) # 3 print("Está resolvido?", meu_cubo.esta_resolvido) # False print("Quanto movimentos?", meu_cubo.movimentos) # 1
Tamanho: (3, 3) Está resolvido? False Quanto movimentos? 0 Girei a face superior. Já executamos 1 movimento(s) Tamanho: (3, 3) Está resolvido? False Quanto movimentos?
Por que é tão vantajoso organizar um código com classes, especialmente em projetos mais complexos?

Vamos continuar com o exemplo do cubo mágico. Imagina que você quer criar um aplicativo que resolva o cubo mágico automaticamente. Se você decidir programar isso sem usar classes, vai acabar com um monte de variáveis e funções soltas pelo código: cor_face_superior, estado_atual_do_cubo, func_girar_direita(), func_verificar_se_esta_resolvido() e por aí vai.
Que bagunça, né? Agora, se você criar uma classe CuboMagico, vai encapsular todos esses dados e comportamentos em um lugar só! Isso torna o código muito mais organizado, fácil de entender e de manter.
Além disso, se quiser simular vários cubos ao mesmo tempo (cada um em um estado diferente), é só criar várias instâncias: cubo1 = CuboMagico(), cubo2 = CuboMagico(), etc. Viu como fica mais prático? Na prática, o que se costuma fazer, especialmente para algo tão complexo como um cubo mágico, é codificar toa da classe em um módulo (arquivo.py) separado, e apenas importá-lo em seu código:
# criamos um arquivo "cubomagico.py" com o seguinte código: class CuboMagico: def init(self, tamanho): self.tamanho = (tamanho,tamanho) self.esta_resolvido = False self.movimentos = 0 self.estado = self.estado_inicial() def estado_inicial(self): # função que inicializa o estado inicial de cada peça do cubo conforme seu tamanho estado = [] # Não precisamos fazer isso aqui ;) return estado def girar_face_superior(self): # Implementação do método girar_face_superior self.movimentos += 1 print(f"Girei a face superior. Já executamos {self.movimentos} movimento(s)")
# Chamamos o arquivo em nosso código principal: from cubomagico import CuboMagico cubo_2 = CuboMagico(4) cubo_2.girar_face_superior()
Girei a face superior. Já executamos 1 movimento(s)
Para finalizar, vamos pensar nas vantagens de planejar seus projetos pensando em objetos desde o início. No nosso exemplo do cubo mágico, a classe poderia ter atributos como faces, historico_de_movimentos, tempo_desde_inicio e métodos como girar_face(), desfazer_ultimo_movimento(), resolver() e embaralhar().
E aí, consegue imaginar que outros atributos e métodos seriam úteis? Talvez um método para salvar o estado atual do cubo? Ou um atributo para contar quantos movimentos foram necessários para resolver?
E tem mais: uma das maiores vantagens da POO é que você pode usar classes criadas por outras pessoas importando módulos e bibliotecas! Por exemplo, se você estiver realmente criando aquele aplicativo para resolver o cubo mágico, não precisa começar do zero.
Pode dar aquela pesquisada e descobrir que já existe uma biblioteca como rubik_solver ou pycuber que já tem classes prontas para representar e manipular o cubo. Basta instalar com pip install e importar no seu código!

Algo como from pycuber import Cube e pronto - você já tem acesso a uma classe super completa para trabalhar. Isso é o que chamamos de usar APIs (Application Programming Interfaces), que são interfaces que permitem que seu código se comunique com código escrito por outras pessoas.
As bibliotecas Python são cheias de classes úteis! Quer lidar com datas? Use a classe datetime. Quer criar interfaces gráficas? Use as classes do tkinter ou PyQt.
Quer trabalhar com aprendizado de máquina?
As classes do scikit-learn estão aí para isso! A programação orientada a objetos nos permite não só organizar melhor nosso próprio código, mas também aproveitar o trabalho de toda a comunidade Python mundial.
Então, da próxima vez que estiver planejando um projeto em Python, lembre-se: divida seu problema em objetos, defina claramente o que cada objeto "sabe" (atributos) e o que cada objeto "faz" (métodos), e veja como tudo fica mais organizado e intuitivo.
E não se esqueça de verificar se já não existem bibliotecas com classes prontas que podem te ajudar a resolver o problema! Por que reinventar a roda, não é mesmo? A programação orientada a objetos é sua amiga, use-a!

Comentários