Classes e Objetos
Nas últimas lições, organizamos código usando funções — uma abordagem "procedural" focada em "o que fazer." Programação Orientada a Objetos (POO) foca em "quem faz" — empacotando dados e os métodos que operam nesses dados em um objeto. Tudo em Python é um objeto; entender POO é um passo fundamental.
1. O que são Classes e Objetos
Uma classe é um projeto; um objeto é uma instância concreta criada a partir desse projeto.
# Define uma classe "Cachorro" — o projeto
class Cachorro:
pass
# Cria objetos "Cachorro" específicos a partir do projeto
my_dog = Cachorro()
print(type(my_dog)) # <class '__main__.Cachorro'>
print(my_dog) # <__main__.Cachorro object at 0x...>
Assim como "cachorro" como raça é um conceito (classe), o cachorro específico chamado Rex que você possui é uma instância (objeto). Uma classe pode criar inúmeros objetos.
2. __init__: O Método Construtor
Ao criar um objeto, o método __init__ é automaticamente chamado para inicializar os atributos do objeto:
class Cachorro:
"""Classe Cachorro"""
def __init__(self, nome, idade):
self.nome = nome # Atributo de instância
self.idade = idade
# Passa parâmetros ao criar objetos
dog1 = Cachorro("Rex", 3)
dog2 = Cachorro("Bolinha", 1)
print(dog1.nome) # Rex
print(dog2.nome) # Bolinha
print(dog1.idade) # 3
__init__ não é o construtor — o objeto é criado antes de ser chamado. O construtor real é __new__, mas você quase nunca precisa tocá-lo. O primeiro parâmetro de __init__ é sempre self, representando a instância atual do objeto.
Exemplo: Definindo uma Classe Aluno (Dificuldade ⭐)
class Aluno:
"""Classe Aluno"""
def __init__(self, nome, matricula, nota):
self.nome = nome
self.matricula = matricula
self.nota = nota
def apresentar(self):
"""Auto-apresentação"""
return f"Meu nome é {self.nome}, matrícula: {self.matricula}, nota: {self.nota}."
def is_aprovado(self):
"""Verifica se está aprovado"""
return self.nota >= 60
# Cria objetos aluno
s1 = Aluno("João Silva", "2024001", 85)
s2 = Aluno("Maria Souza", "2024002", 45)
print(s1.apresentar()) # Meu nome é João Silva, matrícula: 2024001, nota: 85.
print(s2.apresentar()) # Meu nome é Maria Souza, matrícula: 2024002, nota: 45.
print(f"João está aprovado? {s1.is_aprovado()}") # True
print(f"Maria está aprovada? {s2.is_aprovado()}") # False
3. Métodos: Comportamentos dos Objetos
Funções definidas dentro de uma classe são chamadas de métodos. Seu primeiro parâmetro é sempre self — representando o próprio objeto que chama o método.
class Calculadora:
"""Calculadora simples"""
def __init__(self):
self.resultado = 0
def add(self, valor):
self.resultado += valor
return self
def subtrair(self, valor):
self.resultado -= valor
return self
def mostrar(self):
return self.resultado
calc = Calculadora()
calc.add(10)
calc.subtrair(3)
print(calc.mostrar()) # 7
# Encadeamento de métodos — cada método retorna self
resultado = Calculadora().add(10).subtrair(3).add(5).mostrar()
print(resultado) # 12
self podem ser encadeados. Muitas bibliotecas Python (como pandas) usam este padrão extensivamente.
4. Atributos de Instância vs. Atributos de Classe
Atributos podem ser definidos na instância (únicos para cada objeto) ou na classe (compartilhados por todos os objetos):
class Aluno:
# Atributo de classe — compartilhado por todos os alunos
escola = "Escola Primeiro Grau"
total_count = 0
def __init__(self, nome):
# Atributo de instância — único para cada aluno
self.nome = nome
Aluno.total_count += 1
s1 = Aluno("João Silva")
s2 = Aluno("Maria Souza")
# Atributos de classe acessados via nome da classe
print(Aluno.escola) # Escola Primeiro Grau
print(Aluno.total_count) # 2
# Também acessíveis via instâncias (se não houver atributo de instância com o mesmo nome)
print(s1.escola) # Escola Primeiro Grau
print(s2.escola) # Escola Primeiro Grau
# Modificar um atributo de classe afeta todas as instâncias
Aluno.escola = "Escola Segundo Grau"
print(s1.escola) # Escola Segundo Grau
Exemplo: Conta Bancária (Dificuldade ⭐⭐)
class ContaBancaria:
"""Conta bancária"""
nome_banco = "Python Bank" # Atributo de classe
taxa_juros = 0.003 # Taxa de juros anual 0.3%
def __init__(self, titular, saldo=0):
self.titular = titular # Atributo de instância
self.saldo = saldo # Atributo de instância
def depositar(self, valor):
self.saldo += valor
return f"Depositado {valor}, saldo: {self.saldo}"
def sacar(self, valor):
if valor > self.saldo:
return "Saldo insuficiente!"
self.saldo -= valor
return f"Sacado {valor}, saldo: {self.saldo}"
def juros_anuais(self):
"""Calcula juros anuais"""
juros = self.saldo * ContaBancaria.taxa_juros
return f"Juros anuais: {juros:.2f}"
acc1 = ContaBancaria("João Silva", 10000)
acc2 = ContaBancaria("Maria Souza", 5000)
print(acc1.depositar(5000)) # Depositado 5000, saldo: 15000
print(acc2.sacar(2000)) # Sacado 2000, saldo: 3000
print(acc1.juros_anuais()) # Juros anuais: 4.50
# Todas as contas compartilham a mesma taxa de juros
print(acc1.taxa_juros) # 0.003
print(acc2.taxa_juros) # 0.003
Casos de Uso Comuns
- Modelagem de dados: Mapeie entidades do mundo real para código — usuários, pedidos, produtos são todos representados por classes.
- Gerenciamento de estado: Objetos mantêm estado (atributos), métodos manipulam esse estado — ex.: personagens de jogo, carrinhos de compras.
- Organização de código: Dados e funções relacionadas são empacotados juntos, mais limpo que funções dispersas.
- Extensão de framework: Models do Django, aplicação Flask, componentes GUI são todos implementados via classes.
❓ Perguntas Frequentes
P: Qual a diferença entre um método e uma função? R: Um método é uma função definida dentro de uma classe, com
selfcomo primeiro parâmetro. Funções podem existir independentemente; métodos devem ser chamados via um objeto ou classe. Essencialmente, métodos são funções onde Python passa automaticamente o chamador como primeiro argumento. P: Oselfpode ser renomeado para outra coisa? R: Tecnicamente sim, mas nunca mude isso.selfé uma regra rígida na comunidade Python. Mudar o nome funcionaria, mas qualquer um lendo seu código (incluindo você no futuro) acharia estranho. Sempre useself. P: Quando devo usar uma classe vs. uma função? R: Se você precisa manter estado (dados), use uma classe — como uma conta bancária rastreando saldo. Se você está fazendo um cálculo único (entrada -> processamento -> saída), use uma função — como conversão de temperatura. Uma regra simples: se você precisa apenas de 1-2 funções, funções bastam; se múltiplas funções relacionadas compartilham os mesmos dados, use uma classe.
📖 Resumo
- Uma classe é um projeto; um objeto é uma instância concreta criada a partir dele
__init__é o método de inicialização, automaticamente chamado ao criar um objeto- O primeiro parâmetro dos métodos é
self, representando o objeto atual - Atributos de instância são únicos para cada objeto; atributos de classe são compartilhados por todos os objetos
- Classes empacotam dados e os métodos que operam nesses dados juntos
📝 Atividades
-
Iniciante (Dificuldade ⭐): Defina uma classe
Carrocom atributosmarca,corevelocidade. Inclua um métodoacelerar(valor)para aumentar a velocidade e um métodomostrar_velocidade()para exibir a velocidade atual. -
Intermediário (Dificuldade ⭐⭐): Defina uma classe
Aluno. Use um atributo de classe para rastrear o número total de alunos, e atributos de instância para registrar o nome e a nota de cada aluno. Implemente um métodoget_grade()que retorna uma letra (A, B, C, D). -
Avançado (Dificuldade ⭐⭐⭐): Defina uma classe
Bibliotecae uma classeLivro.Livrotem título, autor e status de empréstimo.Bibliotecatem quatro métodos:adicionar_livro(livro),emprestar(titulo),devolver(titulo)emostrar_livros().



