Introdução às Classes Python e Programação Orientada a Objetos [Guia para Iniciantes]
Para executar Python no prompt de comando ou PowerShell no seu PC, é necessário baixar e instalar o Python.
Se ainda não o fez, consulte o artigo Instalação do Python e configuração do ambiente de desenvolvimento para instalar o Python.
Olá a todos que estão apenas começando no mundo do desenvolvimento web! Desta vez, vamos explicar de uma forma mais clara do que em qualquer outro lugar o importante conceito de "Programação Orientada a Objetos (POO)", adotado em muitas linguagens, e o seu núcleo em Python, as "classes". Não precisa ter medo dos termos técnicos. Ao final deste artigo, você certamente entenderá e dirá: "Ah, então é isso!".
O maior objetivo deste artigo é fazer com que você experimente a "alegria de ver o código funcionar". Deixe a teoria complicada para depois e vamos primeiro sentir a conveniência da programação orientada a objetos mexendo em um código que você pode simplesmente copiar e colar!
Afinal, o que é Programação Orientada a Objetos?
Quando você ouve "Orientada a Objetos", pode parecer difícil, certo? Mas, na verdade, é um conceito que está por toda parte em nosso dia a dia.
Uma analogia muito comum é a de uma "forma de biscoito" e um "biscoito".
- Classe (Class): É a "forma de biscoito". Serve como um projeto que define o formato e quais ingredientes (como gotas de chocolate ou nozes) ele terá.
- Objeto (Object): É cada "biscoito" individual feito a partir da "forma". Mesmo que sejam feitos da mesma forma, alguns podem ter coberturas diferentes ou estar um pouco mais assados, dando a cada um sua própria identidade.
No mundo da programação, uma vez que você cria este "projeto" (a classe), você pode criar de forma eficiente e em massa "coisas" concretas (objetos) a partir dele. Este é o conceito fundamental da POO. Em um site, tratar elementos como "usuários", "posts de blog" ou "produtos" como objetos individuais permite organizar sistemas complexos de forma clara.
O Básico das Classes Python: Vamos Criar um Projeto
Então, vamos direto ao ponto e criar um "projeto", ou uma classe, em Python. Vamos usar o tema de cachorros (Cachorro) para esta seção.
1. A classe mais simples
Primeiro, vamos definir uma classe vazia. Mesmo assim, já é um "projeto" válido.
# Define uma classe (projeto) chamada Cachorro
class Cachorro:
pass # pass significa "não fazer nada". É usado quando uma declaração é sintaticamente necessária, mas você não tem código para executar.
# Cria um objeto (instância) concreto de cachorro a partir da classe Cachorro
meu_cachorro = Cachorro()
# Vamos imprimir o que é meu_cachorro
print(meu_cachorro)
Resultado da execução:
<__main__.Cachorro object at 0x10e28a2d0>
Olhando o resultado, você pode ver que um objeto da classe `Cachorro` foi criado. (A parte `0x...` irá variar dependendo do seu ambiente de execução).
2. Dando personalidade com o método `__init__`
A seguir, assim como adicionamos gotas de chocolate a um biscoito, vamos dar ao nosso cachorro informações específicas (chamadas de propriedades ou atributos) como um "nome" e uma "raça". Para fazer isso, usamos um método especial (uma função dentro de uma classe) chamado `__init__`. Este é um método de inicialização que é executado automaticamente no momento em que um objeto é criado.
class Cachorro:
# O método de inicialização, chamado automaticamente quando um objeto é criado
def __init__(self, nome, raca):
# Salva os dados no objeto usando o formato self.nome_da_variavel
self.nome = nome
self.raca = raca
print(f"{self.nome} ({self.raca}) nasceu!")
# Cria um objeto "Shiba Inu" chamado "Pochi"
cachorro1 = Cachorro("Pochi", "Shiba Inu")
# Cria um objeto "Akita" chamado "Hachi"
cachorro2 = Cachorro("Hachi", "Akita")
# Vamos exibir o nome e a raça de cada um
print(f"Nome do primeiro cachorro: {cachorro1.nome}")
print(f"Raça do primeiro cachorro: {cachorro1.raca}")
print(f"Nome do segundo cachorro: {cachorro2.nome}")
print(f"Raça do segundo cachorro: {cachorro2.raca}")
O primeiro argumento do `__init__`, `self`, é uma palavra-chave especial que se refere à instância que está sendo criada. Pense nisso como uma convenção. Ao escrever `self.nome = nome`, você está vinculando dados ao objeto, como se estivesse dizendo "o nome deste objeto é...".
Resultado da execução:
Pochi (Shiba Inu) nasceu!
Hachi (Akita) nasceu!
Nome do primeiro cachorro: Pochi
Raça do primeiro cachorro: Shiba Inu
Nome do segundo cachorro: Hachi
Raça do segundo cachorro: Akita
Apenas chamando a classe como `Cachorro("Pochi", "Shiba Inu")`, o método `__init__` é executado, criando objetos com suas respectivas informações. Você pode acessar as informações que um objeto contém usando um `.` (ponto), como em `cachorro1.nome`.
3. Definindo comportamento com métodos
Os objetos podem ter não apenas dados (atributos), mas também "comportamentos" (métodos). Para um cachorro, vamos adicionar o comportamento de "latir".
class Cachorro:
def __init__(self, nome, raca):
self.nome = nome
self.raca = raca
# Adiciona um comportamento (método) para o cachorro latir
def latir(self):
return f"{self.nome}: Au au!"
# Cria um objeto
meu_cachorro = Cachorro("Koro", "Vira-lata")
# Chama o método latir
cumprimento = meu_cachorro.latir()
print(cumprimento)
Você apenas define uma função dentro da classe usando `def`. Novamente, não se esqueça de incluir `self` como o primeiro argumento. Através do `self`, você pode acessar o próprio nome do objeto (`self.nome`).
Resultado da execução:
Koro: Au au!
Tópico Avançado: Reutilizando Projetos com "Herança" de Classes
É aqui que a programação orientada a objetos se torna realmente poderosa. Usando um mecanismo chamado "herança", você pode criar facilmente uma nova classe adicionando ou alterando funcionalidades com base em uma classe existente (projeto).
Por exemplo, vamos criar uma nova classe "CaoGuia" baseada em nossa classe `Cachorro` anterior. Um cão-guia é um tipo de cachorro, então ele tem um "nome" e uma "raça" e a capacidade básica de "latir". Além disso, ele tem o trabalho especial (método) de "ajudar pessoas".
# A classe pai base (superclasse)
class Cachorro:
def __init__(self, nome, raca):
self.nome = nome
self.raca = raca
print(f"Um cachorro chamado {self.nome} nasceu. A raça é {self.raca}.")
def latir(self):
return f"{self.nome}: Au!"
# Cria uma nova classe filha (subclasse) que herda da classe Cachorro
class CaoGuia(Cachorro): # Escreva o nome da classe pai nos parênteses
def ajudar(self):
return f"{self.nome} está guiando uma pessoa com segurança."
# Cria um objeto CaoGuia
cao_guia = CaoGuia("Elle", "Labrador Retriever")
# Métodos da classe pai (Cachorro) também podem ser usados
print(cao_guia.latir())
# O método único adicionado na classe filha (CaoGuia)
print(cao_guia.ajudar())
Simplesmente escrevendo o nome da classe base nos parênteses após o nome da nova classe, como `class CaoGuia(Cachorro):`, a herança está completa. Assim, `CaoGuia` herda todos os atributos (`nome`, `raca`) e métodos (`latir`) de `Cachorro`. Isso aumenta muito a reutilização de código e é muito eficiente.
Resultado da execução:
Um cachorro chamado Elle nasceu. A raça é Labrador Retriever.
Elle: Au!
Elle está guiando uma pessoa com segurança.
Exemplo Prático: Uma Classe para Gerenciar Posts de Blog
Agora, vamos ver um exemplo mais próximo de um cenário real de produção web. Criaremos uma classe `PostBlog` para gerenciar artigos em um site de blog. Um artigo tem um "título", "conteúdo" e "autor", e daremos a ele uma função para "exibir o post".
import textwrap
class PostBlog:
def __init__(self, titulo, conteudo, autor):
self.titulo = titulo
self.conteudo = conteudo
self.autor = autor
# Um método para exibir as informações do artigo de forma organizada
def exibir(self):
print("--------------------")
print(f"Título: {self.titulo}")
print(f"Autor: {self.autor}")
print("--- Conteúdo ---")
# Quebra e exibe o texto longo
print(textwrap.fill(self.conteudo, width=40))
print("--------------------")
# Cria múltiplos objetos de post
post1 = PostBlog(
"Introdução às Classes Python",
"A programação orientada a objetos é uma forma de pensar na qual você monta programas como se fossem componentes. Uma classe é um projeto e um objeto é a instância real.",
"Taro Yamada"
)
post2 = PostBlog(
"O Básico do Web Design",
"Um bom design considera não apenas a beleza visual, mas prioriza a facilidade de uso para o usuário. Espaçamento e esquemas de cores são cruciais.",
"Hanako Sato"
)
# Exibe os artigos
post1.exibir()
post2.exibir()
Ao tratar cada artigo como um objeto como este, os dados (como o título) e o comportamento (a função de exibição) são agrupados, tornando o gerenciamento muito mais fácil.
Resultado da execução:
--------------------
Título: Introdução às Classes Python
Autor: Taro Yamada
--- Conteúdo ---
A programação orientada a objetos é
uma forma de pensar na qual você monta
programas como se fossem componentes.
Uma classe é um projeto e um objeto é a
instância real.
--------------------
--------------------
Título: O Básico do Web Design
Autor: Hanako Sato
--- Conteúdo ---
Um bom design considera não apenas a
beleza visual, mas prioriza a
facilidade de uso para o usuário.
Espaçamento e esquemas de cores são
cruciais.
--------------------
[Experimente Você Mesmo!] Um Exemplo de Código Python Completo
A espera acabou! Aqui, apresentamos o código completo para um "Programa de Gerenciamento de Usuários" que reúne tudo o que abordamos. Você pode salvar este código como um arquivo `.py` e executá-lo no terminal (ou prompt de comando) do seu computador. Vá em frente e experimente a "alegria de vê-lo funcionar!"
Como Executar
- Copie todo o bloco de código abaixo.
- Cole-o em um editor de texto (como o VSCode) e salve-o com o nome `gerenciador_usuarios.py`.
- Abra seu terminal e navegue até o diretório onde você salvou o arquivo.
- Digite `python gerenciador_usuarios.py` e pressione Enter.
Se você não tiver o Python instalado no seu PC, por favor, baixe-o em python.org.
# gerenciador_usuarios.py
class Usuario:
"""
Uma classe para representar informações de usuário para um site
"""
def __init__(self, id_usuario, nome, email):
self.id_usuario = id_usuario
self.nome = nome
self.email = email
self.esta_ativo = True # Usuário ativo por padrão
def obter_perfil(self):
"""
Formata e retorna as informações do perfil do usuário
"""
status = "Ativo" if self.esta_ativo else "Inativo"
return f"ID: {self.id_usuario}\nNome: {self.nome}\nEmail: {self.email}\nStatus: {status}"
def desativar(self):
"""
Desativa o usuário
"""
self.esta_ativo = False
print(f"O usuário '{self.nome}' foi desativado.")
# A parte que executa o processo principal
if __name__ == "__main__":
# Cria múltiplos objetos de usuário
usuario1 = Usuario("web-creator", "Taro Tanaka", "tanaka@example.com")
usuario2 = Usuario("designer-sato", "Hanako Sato", "sato@example.com")
# Exibe os perfis
print("--- Lista de Usuários ---")
print(usuario1.obter_perfil())
print("-" * 20)
print(usuario2.obter_perfil())
print("\n" + "=" * 20 + "\n")
# Vamos tentar desativar um usuário
usuario2.desativar()
print("\n--- Lista de Usuários Após as Alterações ---")
print(usuario1.obter_perfil())
print("-" * 20)
print(usuario2.obter_perfil())
Ao executar este código, seu terminal deve exibir o seguinte:
Exemplo de Saída:
--- Lista de Usuários ---
ID: web-creator
Nome: Taro Tanaka
Email: tanaka@example.com
Status: Ativo
--------------------
ID: designer-sato
Nome: Hanako Sato
Email: sato@example.com
Status: Ativo
====================
O usuário 'Hanako Sato' foi desativado.
--- Lista de Usuários Após as Alterações ---
ID: web-creator
Nome: Taro Tanaka
Email: tanaka@example.com
Status: Ativo
--------------------
ID: designer-sato
Nome: Hanako Sato
Email: sato@example.com
Status: Inativo
O que você acha? Usando classes, as informações do usuário e suas operações relacionadas (como desativação) são organizadas de forma clara, o que provavelmente faz você sentir que o código é mais fácil de ler.
Pontos a Observar / Erros Comuns
Finalmente, vamos apresentar alguns pontos em que os iniciantes costumam tropeçar ao trabalhar com classes.
- Esquecer o `self`: Se você esquecer de escrever `self` como o primeiro argumento ao definir um método, ou esquecer de adicionar `self.` (como em `self.nome`) ao acessar um atributo dentro de um método, você receberá um erro. Lembre-se da regra: "Dentro de uma classe, acesse tudo através do `self`".
- Errar a grafia de `__init__`: `__init__` tem dois underscores antes e depois. Se você escrever com apenas um, como `_init_`, ele será interpretado como um método regular e não será chamado automaticamente como um inicializador.
- Esquecer os `()` ao instanciar: Se você esquecer os parênteses, como em `meu_cachorro = Cachorro`, você não criará um objeto. Em vez disso, a própria classe será atribuída à variável. Sempre inclua os parênteses, como em `meu_cachorro = Cachorro()`.
Para o Próximo Passo
Agora que você entende o básico de classes и programação orientada a objetos, vamos tentar usar as úteis bibliotecas padrão do Python. Lidar com datas e horas é uma tarefa muito comum em programação.
No próximo artigo, aprenderemos como obter a data atual e realizar cálculos de data usando o módulo `datetime`.
→ Como Lidar com Datas e Horas com o Módulo datetime