Módulo 16 - Projeto final: agenda de contatos
Modelando a agenda com classes
11 min de leitura · por Cesar Gargiulo, revisado pela equipe ValorFinal e GuardiaSec · Atualizado em 01/07/2026
O que você vai aprender
- Criar a classe Contato com atributos nome, telefone e e-mail.
- Escrever um método __str__ que mostra o contato de forma legível.
- Criar a classe Agenda com uma lista interna de contatos.
- Rodar o esqueleto do programa e confirmar que os objetos existem.
Ouvir o resumo desta aula
Um recap de cerca de 2 minutos na voz do Valim, para ouvir no trânsito ou na academia.
Ler a transcrição do resumo
Resumo da aula: Modelando a agenda com classes.
Os objetivos desta aula. Criar a classe Contato com atributos nome, telefone e e-mail. Escrever um método __str__ que mostra o contato de forma legível. Criar a classe Agenda com uma lista interna de contatos. Rodar o esqueleto do programa e confirmar que os objetos existem.
Veja o essencial, parte por parte.
A classe Contato. Contato é uma classe com três atributos: nome, telefone e email.
A classe Agenda. Com o contato pronto, a agenda é quase natural.
Por que classes e não dicionários. Uma dúvida honesta: por que não guardar cada contato como um dicionário, algo como {"nome": "Ana", "telefone": "..."}?
Esse foi o resumo do essencial. Para se aprofundar, leia a aula completa e responda os exercícios.
A classe Contato
Todo projeto de orientação a objetos começa perguntando quais coisas existem no problema. Na agenda, existem duas: um contato e a agenda que reúne os contatos. Comece pelo contato, porque a agenda depende dele. Um contato é um agrupamento de três valores que andam juntos: nome, telefone e e-mail. Guardar isso em três variáveis soltas seria frágil. Uma classe amarra os três em um objeto só, com nome próprio, e abre espaço para dar comportamento a ele depois.
class Contato:
def __init__(self, nome, telefone, email=""):
self.nome = nome
self.telefone = telefone
self.email = email
def __str__(self):
return f"{self.nome} | {self.telefone} | {self.email}"A classe Contato: três atributos e um __str__ que a mostra em uma linha.
Duas escolhas merecem atenção. O parâmetro email recebe um valor padrão, a string vazia, o que o torna opcional: dá para criar um contato só com nome e telefone. E o método __str__ define como o contato aparece quando você o imprime. Sem ele, print(contato) mostraria algo técnico e inútil como <Contato object at 0x7f...>. Com ele, mostra Ana | 11999998888 | ana@exemplo.com, pronto para o usuário ler. É um detalhe pequeno que muda toda a experiência do programa.
A classe Agenda
Com o contato pronto, a agenda é quase natural. Ela é o objeto que guarda muitos contatos. A informação que ela precisa manter é uma coleção, e a coleção certa aqui é uma lista: os contatos têm ordem e podem ser adicionados e removidos. No __init__, a agenda começa com uma lista vazia. Ainda não há métodos para operar sobre ela; isso é o assunto da próxima aula. Por enquanto, a classe só reserva o lugar onde os contatos vão morar.
class Agenda:
def __init__(self):
self.contatos = []
# Testando o esqueleto do programa
agenda = Agenda()
ana = Contato("Ana Souza", "11999998888", "ana@exemplo.com")
agenda.contatos.append(ana)
print(len(agenda.contatos)) # 1
print(agenda.contatos[0]) # Ana Souza | 11999998888 | ana@exemplo.comA classe Agenda guarda uma lista de contatos. O teste no fim confirma o esqueleto.
Rode esse arquivo e observe o que acontece. Você cria uma agenda vazia, cria um contato, coloca o contato na lista da agenda com append e confere. O print(agenda.contatos[0]) mostra a linha bonita porque a classe Contato tem __str__. Neste momento, o programa já tem os dois tipos de objeto que importam. Falta dar à agenda métodos próprios, para que ninguém precise mexer diretamente na lista contatos de fora. Escrever agenda.contatos.append(ana) funciona, mas o certo é agenda.adicionar_contato(ana), e é o que vem a seguir.
Por que classes e não dicionários
Uma dúvida honesta: por que não guardar cada contato como um dicionário, algo como {"nome": "Ana", "telefone": "..."}? Funcionaria. A diferença é que a classe reúne, no mesmo lugar, os dados e o comportamento. O __str__ vive junto do contato; não é uma função solta que alguém pode esquecer de usar. Quando a agenda crescer e cada contato precisar de mais capacidades, como se transformar em dicionário para salvar, essas capacidades ficam todas na classe, organizadas. É a diferença entre uma pasta com etiqueta e papéis espalhados na mesa.
Contato como dicionário
- Dados soltos: {"nome": ..., "telefone": ...}
- Formatar para exibir é função externa
- Fácil esquecer um campo ao criar
- Comportamento espalhado pelo código
Contato como classe
- Dados e comportamento no mesmo objeto
- __str__ mora dentro do contato
- O __init__ documenta os campos esperados
- Tudo do contato fica em um lugar só
Isso não significa que dicionários sejam ruins. Para dados muito simples e passageiros, eles são ótimos. A regra prática é: quando um agrupamento de dados começa a ganhar comportamento e a se repetir pelo programa, promova-o a classe. O contato é exatamente esse caso. Curiosamente, quando formos salvar em JSON, cada contato vira um dicionário de novo, só que de propósito e por um instante. As duas ideias convivem, cada uma no seu momento.
Teste rápido
Qual é o papel do método __str__ na classe Contato?
Perguntas frequentes
- Por que email tem um valor padrão e nome e telefone não?
- Porque um contato quase sempre tem nome e telefone, mas nem sempre tem e-mail. Dar a email o valor padrão vazio o torna opcional: você pode criar Contato("Ana", "11999998888") sem informar e-mail. Parâmetros com padrão precisam vir depois dos sem padrão.
- O que é self, que aparece em todos os métodos?
- self é o próprio objeto, passado automaticamente para cada método. É por meio dele que o método acessa os atributos daquele objeto específico, como self.nome. Você viu isso a fundo no módulo de orientação a objetos; aqui ele reaparece na prática.
- Preciso escrever __str__ em toda classe que eu criar?
- Não em todas, mas é muito recomendado em classes cujos objetos você vai imprimir ou mostrar para o usuário, como o Contato. Ele deixa a saída legível de graça. Para classes internas que nunca aparecem na tela, é dispensável.
- A lista contatos poderia ser um conjunto ou um dicionário?
- Poderia, dependendo da necessidade. Um conjunto evitaria repetições, mas perderia a ordem. Um dicionário por nome aceleraria a busca. Escolhemos a lista por ser simples e preservar a ordem de inclusão, o que basta para uma agenda pequena e didática.
- Por que criar a agenda vazia se ela ainda não faz nada?
- Porque o projeto é incremental. Ter as duas classes existindo, mesmo simples, já é um programa que roda. Nas próximas aulas você acrescenta métodos a esse esqueleto sem precisar reescrever nada. Cada passo se apoia no anterior.
- Onde devo salvar esse código no meu computador?
- Crie um arquivo chamado agenda.py em uma pasta do projeto. É nele que o programa vai crescer a cada aula. Na aula de testes, você criará um segundo arquivo ao lado, para testar sem bagunçar o principal.
Fontes
Seu progresso fica salvo neste aparelho. Assinantes sincronizam entre os aparelhos.