Uma classe é uma definição — ela descreve como um objeto vai ser, mas não é o objeto em si. Pense como um projeto de engenharia: o projeto não é o produto, mas contém tudo que o produto precisa ter.
Você define a estrutura uma vez e pode criar quantas instâncias precisar, cada uma com seus próprios dados mas compartilhando a mesma estrutura e comportamentos.
class MinhaClasse:
pass # classe vazia
obj = MinhaClasse() # instanciar = criar objeto O pass é necessário porque Python exige ao menos uma instrução no corpo da classe.
O __init__ é o construtor da classe — executado automaticamente quando você cria um objeto. É onde você define os atributos iniciais.
Cachorro__init__ passando esse objeto como self, "Rex" como nome e 3 como idadeself.nome = nome guarda "Rex" dentro do objetorexself é uma convenção para o primeiro parâmetro de qualquer método de instância. Ele recebe automaticamente o objeto que chamou o método. Nunca quebre essa convenção.
class Cachorro:
def __init__(self, nome, idade):
self.nome = nome
self.idade = idade
rex = Cachorro("Rex", 3)
bolt = Cachorro("Bolt", 1)
rex.nome = "Max"
print(bolt.nome) # Bolt — bolt não mudou Quando você escreve o código da classe, você ainda não sabe o nome que o usuário vai dar para o objeto. Você não sabe se vai ser rex, bolt ou totó.
O self funciona como um nome genérico (um pronome) dentro da classe que significa: "este objeto aqui que está executando a ação agora".
Veja a diferença entre como você escreve e como o Python lê:
class Cachorro:
def __init__(self, nome):
self.nome = nome
rex = Cachorro("Rex") Quando você faz Cachorro("Rex"), o Python reserva um espaço na memória e faz o seguinte:
"Ei, função __init__, preencha os dados para este novo objeto que acabei de criar. O self dele vai ser essa região de memória que vou chamar de rex."
Porque o Python sempre envia o próprio objeto como o primeiro argumento de qualquer função dentro da classe, de forma automática.
# Se você chama:
rex.latir()
# Python na verdade executa:
Cachorro.latir(rex) O self recebe o rex para que, dentro da função, o código saiba se deve usar o latido de um Labrador ou de um Pinscher.
Um método de instância é uma função dentro de uma classe que sempre recebe self como primeiro parâmetro. Através de self, o método acessa e modifica os atributos do objeto.
# Função avulsa
def latir(nome):
print(f"{nome} diz: Au!")
# Método — o dado pertence ao objeto
class Cachorro:
def latir(self):
print(f"{self.nome} diz: Au!") rex.latir() — Python automaticamente passa rex como self. Nos bastidores: Cachorro.latir(rex).
class Aluno:
def calcular_media(self):
return sum(self.notas) / len(self.notas)
def situacao(self):
media = self.calcular_media()
return "Aprovado" if media >= 7 else "Reprovado" self no métodoTodo método de instância precisa dele como o primeiro parâmetro entre os parênteses.
def latir(): Dará erro quando você tentar chamar o método.
def latir(self): self. para acessar atributosDentro da classe, o Python não adivinha que "nome" é o atributo do objeto. Você precisa apontar.
print(nome) O Python dirá que "nome" não está definido.
print(self.nome) __init__Você não pode usar ou alterar algo que não foi "apresentado" ao Python no construtor.
self.notas.append(10) # sem ter criado a lista Vai dar AttributeError.
def __init__(self):
self.notas = [] # criar primeiro Sem os parênteses (), você só está citando o nome do método, não mandando ele agir.
rex.latir O código passa direto e nada acontece.
rex.latir() Agora sim o cachorro late no console.
A Classe é a planta, o Objeto é a casa pronta. Você interage com a casa.
Cachorro.latir() Você está tentando fazer o "molde" latir.
rex = Cachorro()
rex.latir() Você cria o objeto e depois o usa.
self aparece na definição mas não na chamada?Quando você escreve def latir(self):, está dizendo ao Python que esse método pertence a um objeto. Mas quando você chama rex.latir(), o Python já sabe que rex é o objeto — então ele passa o rex como self automaticamente nos bastidores.
É como se o Python traduzisse rex.latir() para Cachorro.latir(rex). Você nunca precisa passar o self explicitamente na chamada.
Cachorro e Cachorro()?Cachorro sem parênteses é a classe em si — o molde, a definição. Você pode até inspecioná-la, mas ela não é um cachorro de verdade.
Cachorro() com parênteses chama o construtor __init__ e fabrica um objeto novo na memória. É a diferença entre a planta arquitetônica e o prédio construído.
Sempre que quiser um objeto para usar, use os parênteses.
__init__?Sim. Se você não escrever um __init__, o Python usa um construtor padrão vazio. Na prática, porém, quase toda classe precisa de um, porque é nele que você define o estado inicial do objeto.
__init__:class Cachorro:
pass
rex = Cachorro()
rex.nome = "Rex" # atributo adicionado depois __init__ — mais organizado e seguro:class Cachorro:
def __init__(self, nome):
self.nome = nome
rex = Cachorro("Rex") # todo cachorro nasce com nome A segunda forma garante que todo objeto nasce com seus dados. Na primeira, você poderia criar um cachorro sem nome e só descobrir o erro lá na frente.
A regra prática: se você tem dados que andam juntos e ações que operam sobre esses dados, crie uma classe. Se é uma operação isolada sem estado, use função.
def celsius_para_fahrenheit(c):
return c * 1.8 + 32 class Termometro:
def __init__(self, celsius):
self.celsius = celsius
def em_fahrenheit(self):
return self.celsius * 1.8 + 32 Se você só precisa converter um valor pontualmente, a função basta. Se precisa representar um termômetro real com estado, use a classe.
Programação Orientada a Objetos com Python
Tecnologia em Análise e Desenvolvimento de Sistemas
revisão
cor = "preto" marca = "Samsung" bateria = 80
ligar() tirar_foto() carregar()
antes do código
Atributos: marca, modelo, bateria, cor.
Métodos: ligar(), tirar_foto(), carregar().
Atributos: titular, saldo, agência.
Métodos: depositar(), sacar(), extrato().
Atributos: nome, matrícula, notas.
Métodos: adicionar_nota(), media(), situacao().
conceito fundamental
Uma classe não é o objeto — é a descrição de como o objeto vai ser.
# Classe = molde
class Cachorro:
pass # ainda vazio, mas já é uma classe!
# Objetos = instâncias do molde
rex = Cachorro()
bolt = Cachorro() fundamentos
__init__ é chamado automaticamente quando você cria um objeto. É onde você define os atributos iniciais.
class Cachorro:
def __init__(self, nome, raca, idade):
self.nome = nome # atributo de instância
self.raca = raca
self.idade = idade
rex = Cachorro("Rex", "Labrador", 3)
bolt = Cachorro("Bolt", "Husky", 1)
print(rex.nome) # Rex
print(bolt.raca) # Husky entendendo o self
self é a referência ao próprio objeto. Python passa o objeto automaticamente como primeiro argumento em todo método.
class Cachorro:
def latir(): # falta self
print("Au!")
rex = Cachorro()
rex.latir() # ERRO! class Cachorro:
def latir(self): # correto
print("Au!")
rex = Cachorro()
rex.latir() # Au! rex.latir() em Cachorro.latir(rex) nos bastidores. O self é o rex.fundamentos
Métodos são funções que vivem dentro da classe e operam sobre os dados do objeto.
class Cachorro:
def __init__(self, nome, idade):
self.nome = nome
self.idade = idade
def latir(self):
print(f"{self.nome} diz: Au!")
def apresentar(self):
print(f"Meu nome é {self.nome} e tenho {self.idade} anos.")
rex = Cachorro("Rex", 3)
rex.latir() # Rex diz: Au!
rex.apresentar() # Meu nome é Rex e tenho 3 anos. instâncias
Alterar um objeto não afeta os outros.
class Pessoa:
def __init__(self, nome, idade):
self.nome = nome
self.idade = idade
def aniversario(self):
self.idade += 1
print(f"Feliz aniversário, {self.nome}! Agora tem {self.idade} anos.")
ana = Pessoa("Ana", 22)
pedro = Pessoa("Pedro", 30)
ana.aniversario() # Feliz aniversário, Ana! Agora tem 23 anos.
print(pedro.idade) # 30 — Pedro não mudou conectando com a aula 01
A calculadora que você fez na semana passada, agora com memória.
class Calculadora:
def __init__(self):
self.historico = [] # atributo: guarda operações
def somar(self, a, b):
resultado = a + b
self.historico.append(f"{a} + {b} = {resultado}")
return resultado
def ver_historico(self):
for item in self.historico:
print(item)
calc = Calculadora()
print(calc.somar(10, 5))
calc.ver_historico() historico. Isso é impossível com funções avulsas.atenção
Todo método de instância precisa de self como primeiro parâmetro, sem exceção.
Dentro da classe, sempre self.nome, nunca só nome.
Todo atributo precisa ser criado no construtor. Usar self.notas sem ter feito self.notas = [] no construtor gera AttributeError.
obj.metodo() é correto, obj.metodo apenas cita o nome da função.
Cachorro é a classe (molde), rex = Cachorro() é o objeto (instância).
exercício
Vamos criar uma classe Aluno do zero, juntos.
Criar classe Aluno com nome, matricula e notas (lista vazia). Método exibir(self) que imprime o nome e a matrícula do aluno.
Adicionar adicionar_nota(nota) e calcular_media() que retorna a média das notas.
Método situacao(): Aprovado (≥7), Recuperação (5–6.9) ou Reprovado (<5).
exercício · parte 1
class Aluno:
def __init__(self, nome, matricula):
self.nome = nome
self.matricula = matricula
self.notas = [] # lista vazia
def exibir(self):
print(f"Aluno: {self.nome} | Matrícula: {self.matricula}")
# Teste
a1 = Aluno("Ana Silva", "2026001")
a1.exibir() exercício · partes 2 e 3
class Aluno:
def __init__(self, nome, matricula):
self.nome = nome
self.matricula = matricula
self.notas = []
def adicionar_nota(self, nota):
self.notas.append(nota)
def calcular_media(self):
if len(self.notas) == 0:
return 0
return sum(self.notas) / len(self.notas)
def situacao(self):
media = self.calcular_media()
if media >= 7: return "Aprovado"
elif media >= 5: return "Recuperação"
else: return "Reprovado"
def exibir(self):
media = self.calcular_media()
situacao = self.situacao()
print(f"Aluno: {self.nome} | Média: {media:.1f} | {situacao}")
a1 = Aluno("Ana Silva", "2026001")
a1.adicionar_nota(8.0)
a1.adicionar_nota(7.5)
a1.adicionar_nota(9.0)
a1.exibir() dúvidas frequentes
Python passa o objeto automaticamente. rex.latir() vira Cachorro.latir(rex) nos bastidores.
Cachorro é a classe em si (o molde). Cachorro() chama o construtor e fabrica um objeto novo na memória.
Sim. Python usa um __init__ vazio padrão. Mas na prática, quase toda classe precisa de um para garantir que todo objeto nasça com seus dados.
Se você tem dados que andam juntos e ações sobre esses dados, use classe. Se é apenas uma operação isolada sem estado, use função.
fechamento
class NomeDaClasse: — como declarar a estrutura __init__(self, ...) — o construtor onde nascem os atributos self — a referência vital ao próprio objeto para casa
Faça o máximo que conseguir e anote suas dúvidas para a próxima aula.
Exercícios: 1 ao 3
básicoExercícios: 4 ao 9
intermediárioExercícios: 10 ao 14
avançadoExercícios: 15 ao 18
desafioexercícios para casa · nível fácil
Crie uma classe Carro com atributos marca, modelo e ano. Adicione um método exibir(self) que imprime as informações do carro. Crie dois objetos diferentes e chame exibir() em ambos.
Crie Pessoa com nome e idade. Adicione apresentar(self) que imprime uma saudação. Crie três instâncias com dados diferentes.
Crie Retangulo com largura e altura. Adicione area(self) e perimetro(self) que retornam os respectivos valores.
exercícios para casa · nível médio
Crie ContaBancaria com titular e saldo. Métodos depositar(valor) e sacar(valor) — saque só funciona com saldo suficiente. Adicione um método exibir(self) que imprime o titular e o saldo atual.
Crie Produto com nome, preco e estoque. Métodos vender(qtd) — sem deixar negativo — e repor(qtd).
Sem olhar os slides — implemente do zero a classe Aluno com nome, matricula, lista de notas, adicionar_nota, calcular_media e situacao. Adicione um método exibir(self) que imprime o nome, a média e a situação do aluno.
Crie Cronometro com segundos = 0. Método avancar(s) soma segundos e em_minutos(self) retorna string como "2 minutos e 35 segundos".
Crie Temperatura com atributo celsius. Métodos para_fahrenheit() e para_kelvin() que retornam os valores convertidos. Adicione um método exibir(self) que imprime as três escalas.
Implemente a Calculadora do slide 9. Adicione limpar_historico() e ultimo_resultado() que retorna o último item ou mensagem se vazio.
exercícios para casa · nível difícil
Crie Pilha com lista vazia. Métodos empilhar(item), desempilhar() — retorna None se vazia —, topo() e esta_vazia(). Teste com 5 operações.
Crie Turma com lista de alunos. Métodos matricular(aluno), listar(), media_turma() e melhores_alunos() — retorna quem tem média acima de 7. Use a classe Aluno do exercício 6.
Crie Agenda com dicionário de contatos. Métodos adicionar(nome, telefone), buscar(nome), remover(nome) e listar() em ordem alfabética.
Expanda o exercício 4 adicionando extrato (lista), ver_extrato() com tipo e valor de cada operação e transferir(outra_conta, valor).
Crie Livro com titulo, autor e disponivel=True. Crie Biblioteca com adicionar_livro, emprestar, devolver e listar_disponiveis.
exercícios para casa · nível avançado
Crie Vetor2D com x e y. Implemente __str__, __add__ (soma de vetores), __eq__ e magnitude() — use import math.
Crie JogoAdivinhacao com número sorteado entre 1 e 100, contador de tentativas e máximo de 10. Métodos adivinhar(n) e reiniciar(). Use import random.
Crie Matriz com linhas e colunas (grade de zeros). Métodos definir(l,c,v), obter(l,c), __str__ formatado e somar(outra).
Crie Personagem com vida=100, ataque e defesa. Método atacar(outro) — dano = max(0, ataque − defesa do outro) — e esta_vivo(). Simule um combate em loop.
Vamos aprofundar o uso de métodos, conhecer o __str__ em detalhes e aprender outras formas de representar um objeto.