Guia de estudo

Aula 18 · Seg, 22/06

Coleções e POO

Guardando muitos objetos com elegância.

Na aula passada salvamos um objeto por vez. Hoje aprendemos a manipular coleções inteiras: list, dict, set e tuple — e como as suas classes conversam com for, in, comprehension e sorted.

list de objetos dict como repositório set sem repetição comprehension sorted(key=)

roteiro da aula

O que vamos aprender hoje

01

Listas de objetos

Guardar vários objetos numa lista só e processar todos com um for.

02

Dict repositório

O dicionário como repositório: a chave aponta direto pro objeto, sem percorrer tudo.

03

Buscar e filtrar

Buscar um objeto, filtrar por critério e iterar — incluindo o set, que elimina repetição.

04

Comprehension + ordenar

List comprehension pra condensar, e sorted(key=lambda) pra ordenar objetos.

ponte com a aula passada

De onde paramos — arquivos (aula 17)

  • 💾 Na aula 17, o salvar() gravava UM objeto por vez no arquivo.
  • 📋 Mas o carregar_todos() já devolvia uma LISTA de objetos de volta — uma coleção.
  • 🎯 Hoje a gente domina essa coleção: como buscar, filtrar, ordenar e deduplicar os objetos com elegância.

o problema

O problema: vários objetos soltos

Quando cada objeto vive numa variável separada, qualquer processamento vira repetição manual.

soltos.py
class Pet:
    def __init__(self, nome, especie, idade):
        self.nome = nome
        self.especie = especie
        self.idade = idade

pet1 = Pet("Rex", "Cão", 4)
pet2 = Pet("Mimi", "Gato", 2)
pet3 = Pet("Thor", "Cão", 7)
pet4 = Pet("Bidu", "Cão", 1)

# Sem coleção, sobra trabalho manual e repetição:
print(pet1.nome, pet1.especie, pet1.idade)   # Rex Cão 4
print(pet2.nome, pet2.especie, pet2.idade)   # Mimi Gato 2
print(pet3.nome, pet3.especie, pet3.idade)   # Thor Cão 7
print(pet4.nome, pet4.especie, pet4.idade)   # Bidu Cão 1
# E se fossem 200 pets? Repetir print 200 vezes é inviável.
Num pet shop de verdade são centenas de pets. Variáveis soltas não escalam — precisamos guardar tudo numa coleção e processar de uma vez.

listas

Lista de objetos

Uma lista guarda vários objetos numa variável só. Um for processa todos — não importa se são 3 ou 300.

lista_de_objetos.py
class Pet:
    def __init__(self, nome, especie, idade):
        self.nome = nome
        self.especie = especie
        self.idade = idade

    def __str__(self):
        return f"{self.nome} ({self.especie}, {self.idade} anos)"

# uma lista guarda vários objetos numa variável só
pets = [Pet("Rex", "Cão", 4), Pet("Mimi", "Gato", 2), Pet("Thor", "Cão", 7)]

print(len(pets))            # 3
for pet in pets:
    print(pet)
# Rex (Cão, 4 anos)
# Mimi (Gato, 2 anos)
# Thor (Cão, 7 anos)
É o __str__ (aula 03) que deixa o print(pet) legível dentro do for. Sem ele, sairia algo como <__main__.Pet object at 0x...>.

panorama

As 4 coleções do Python

item detalhe
list — [ ] Ordenada e mutável. Aceita repetidos e tem índice. É a coleção do dia a dia.
tuple — ( ) Ordenada, mas IMUTÁVEL: depois de criada não muda. Boa pra dados fixos (ex.: coordenadas).
dict — { chave: valor } Mapeia uma chave a um valor. Acesso direto pela chave, sem percorrer tudo. O repositório.
set — set( ) Sem ordem e SEM repetição. Guarda elementos distintos. Ótimo pra eliminar duplicatas.

listas

Operações essenciais de lista

append, len, in, índice, fatia e for — o ferramental que você usa o tempo todo.

operacoes_lista.py
pets = ["Rex", "Mimi", "Thor"]

pets.append("Bidu")             # adiciona no fim
print(pets)                     # ['Rex', 'Mimi', 'Thor', 'Bidu']
print(len(pets))                # 4
print("Mimi" in pets)           # True
print(pets[0])                  # Rex      (índice começa em 0)
print(pets[-1])                 # Bidu     (índice negativo: de trás pra frente)
print(pets[1:3])                # ['Mimi', 'Thor']   (fatia: do 1 ao 2)
for nome in pets:
    print(nome)                 # Rex / Mimi / Thor / Bidu (um por linha)
O índice começa em 0; pets[-1] é sempre o último. A fatia [1:3] vai do índice 1 até o 2 (o 3 fica de fora).

buscar e filtrar

Buscar um objeto na lista

O padrão de busca: percorre com for, compara um atributo, devolve o objeto ao achar — ou None no fim.

buscar.py
class Pet:
    def __init__(self, nome, especie, idade):
        self.nome = nome
        self.especie = especie
        self.idade = idade
    def __str__(self):
        return f"{self.nome} ({self.especie}, {self.idade} anos)"

pets = [Pet("Rex", "Cão", 4), Pet("Mimi", "Gato", 2), Pet("Thor", "Cão", 7)]

def buscar_por_nome(lista, alvo):
    for pet in lista:
        if pet.nome == alvo:
            return pet        # achou: devolve o objeto e para
    return None               # percorreu tudo e não achou

print(buscar_por_nome(pets, "Mimi"))   # Mimi (Gato, 2 anos)
print(buscar_por_nome(pets, "Bidu"))   # None
Devolver None quando não acha é a convenção pythônica — quem chama testa com if resultado is not None. (Daqui a pouco o dict faz essa busca direto pela chave.)

buscar e filtrar

Filtrar com for + append

Montar uma lista nova só com quem passa num critério: lista vazia, for, if, append. É a base do que vem a seguir.

filtrar_for.py
class Pet:
    def __init__(self, nome, especie, idade):
        self.nome = nome
        self.especie = especie
        self.idade = idade
    def __str__(self):
        return f"{self.nome} ({self.especie}, {self.idade} anos)"

pets = [Pet("Rex", "Cão", 4), Pet("Mimi", "Gato", 2), Pet("Thor", "Cão", 7)]

# o jeito tradicional: lista vazia + for + if + append
caes = []
for pet in pets:
    if pet.especie == "Cão":
        caes.append(pet)

for cao in caes:
    print(cao)
# Rex (Cão, 4 anos)
# Thor (Cão, 7 anos)
Esse padrão "lista vazia → for → if → append" aparece o tempo todo. No próximo slide condensamos ele numa linha só.

comprehension

List comprehension — a forma condensada

A comprehension faz o mesmo que for + append, em uma linha. Compare lado a lado — o resultado é idêntico.

comprehension.py
class Pet:
    def __init__(self, nome, especie, idade):
        self.nome = nome
        self.especie = especie
        self.idade = idade
    def __str__(self):
        return f"{self.nome} ({self.especie}, {self.idade} anos)"

pets = [Pet("Rex", "Cão", 4), Pet("Mimi", "Gato", 2), Pet("Thor", "Cão", 7)]

# forma longa: for + append (3 linhas)
caes = []
for pet in pets:
    if pet.especie == "Cão":
        caes.append(pet)

# forma condensada: list comprehension (1 linha) — mesmo resultado
caes = [pet for pet in pets if pet.especie == "Cão"]

for cao in caes:
    print(cao)
# Rex (Cão, 4 anos)
# Thor (Cão, 7 anos)
Leia a comprehension da direita pra esquerda: "pra cada pet em pets, SE for Cão, coloque o pet na lista nova".

comprehension

Comprehension: transformar e filtrar

Dois usos: TRANSFORMAR (mudar cada item) e FILTRAR (escolher itens). A anatomia é sempre a mesma.

transformar_filtrar.py
class Pet:
    def __init__(self, nome, especie, idade):
        self.nome = nome
        self.especie = especie
        self.idade = idade
    def __str__(self):
        return f"{self.nome} ({self.especie}, {self.idade} anos)"

pets = [Pet("Rex", "Cão", 4), Pet("Mimi", "Gato", 2), Pet("Thor", "Cão", 7)]

# TRANSFORMAR: uma lista só com os nomes
nomes = [pet.nome for pet in pets]
print(nomes)                       # ['Rex', 'Mimi', 'Thor']

# FILTRAR: só os pets com 5 anos ou mais
idosos = [pet for pet in pets if pet.idade >= 5]
print([p.nome for p in idosos])    # ['Thor']

# anatomia:  [ expressão   for item in coleção   if condição ]
#              pet.nome     for pet in pets        (sem if = todos)
A expressão na frente decide o que entra na lista: pet.nome devolve nomes; pet devolve o objeto inteiro. O if no fim é opcional — sem ele, todos passam.

comprehension

for + append vs comprehension

Mesmo resultado. À esquerda, quatro linhas e uma variável de acumulação. À direita, uma linha que se lê como uma frase.

for + append — verboso

longo.py
caes = []
for pet in pets:
    if pet.especie == "Cão":
        caes.append(pet)
# 4 linhas + uma lista vazia
# pra inicializar.

comprehension — conciso

curto.py
caes = [pet for pet in pets
        if pet.especie == "Cão"]
# 1 instrução. O Python já
# entende: "a lista dos
# pets que são Cão".
Regra de ouro: use a comprehension quando ela couber em uma linha legível. Se ficar complexa (ifs aninhados, expressões longas), volte pro for — clareza vence concisão.

dict

Dicionário: o repositório por chave

Na lista você procura percorrendo tudo. No dict, a chave aponta DIRETO pro objeto — busca instantânea.

dict_repositorio.py
class Pet:
    def __init__(self, codigo, nome, especie):
        self.codigo = codigo
        self.nome = nome
        self.especie = especie
    def __str__(self):
        return f"[{self.codigo}] {self.nome} ({self.especie})"

# dicionário = repositório: a chave (código) aponta direto pro objeto
repositorio = {
    "P01": Pet("P01", "Rex", "Cão"),
    "P02": Pet("P02", "Mimi", "Gato"),
}

print(repositorio["P01"])     # [P01] Rex (Cão)
print(repositorio["P02"])     # [P02] Mimi (Gato)
# sem percorrer a lista inteira: a chave leva direto ao objeto.
Use dict quando cada objeto tem um identificador natural (código, matrícula, CPF) e você vai buscar por ele. A chave vira o "endereço" do objeto.

dict

Operações de dicionário

Inserir, buscar, testar, remover e percorrer — o ferramental do dict.

operacoes_dict.py
repositorio = {"P01": "Rex", "P02": "Mimi"}

repositorio["P03"] = "Thor"          # inserir/atualizar pela chave
print(repositorio.get("P01"))        # Rex   (busca segura)
print(repositorio.get("P99"))        # None  (chave ausente: devolve None)
print("P02" in repositorio)          # True  (testa se a chave existe)
del repositorio["P02"]               # remover pela chave

print(list(repositorio.keys()))      # ['P01', 'P03']
print(list(repositorio.values()))    # ['Rex', 'Thor']
print(list(repositorio.items()))     # [('P01', 'Rex'), ('P03', 'Thor')]
keys() são as chaves, values() são os valores e items() entrega os dois juntos (chave, valor) — perfeito pra percorrer no for do próximo slide.

dict

Iterar um dicionário de objetos

Com .items() o for recebe a chave E o objeto a cada volta — desempacotados em duas variáveis.

iterar_dict.py
class Pet:
    def __init__(self, codigo, nome, especie):
        self.codigo = codigo
        self.nome = nome
        self.especie = especie
    def __str__(self):
        return f"[{self.codigo}] {self.nome} ({self.especie})"

repositorio = {
    "P01": Pet("P01", "Rex", "Cão"),
    "P02": Pet("P02", "Mimi", "Gato"),
}

# .items() entrega a chave E o valor a cada volta
for codigo, pet in repositorio.items():
    print(f"{codigo} -> {pet}")
# P01 -> [P01] Rex (Cão)
# P02 -> [P02] Mimi (Gato)
for codigo, pet in ...items() desempacota o par numa tacada. Se usasse só for chave in repositorio, viriam apenas as chaves.

dict · a armadilha

A pegadinha do [ ] vs .get()

Buscar uma chave que não existe: o colchete ESTOURA; o .get() devolve None. Escolha o jeito seguro.

repositorio["P99"] — estoura

colchete.py
repositorio = {"P01": "Rex"}
print(repositorio["P99"])
# KeyError: 'P99'
# o programa para com erro se a
# chave não existir.

repositorio.get("P99") — seguro

get.py
repositorio = {"P01": "Rex"}
print(repositorio.get("P99"))
# None
print(repositorio.get("P99", "vazio"))
# vazio  (padrão que você escolhe)
Use [ ] quando tem certeza de que a chave existe; use .get() quando ela PODE não existir. O .get() ainda aceita um valor padrão como 2º argumento.

set

Set: sem repetição, sem ordem

O set guarda elementos DISTINTOS. Jogue uma coleção com repetidos dentro dele e as duplicatas somem.

set_unicidade.py
class Pet:
    def __init__(self, nome, especie):
        self.nome = nome
        self.especie = especie

pets = [Pet("Rex", "Cão"), Pet("Mimi", "Gato"), Pet("Thor", "Cão"), Pet("Lulu", "Gato")]

# set() elimina repetições automaticamente
especies = set(pet.especie for pet in pets)
print(especies)        # {'Cão', 'Gato'}  (a ordem pode variar — set não tem ordem)
print(len(especies))   # 2  (4 pets, mas só 2 espécies distintas)
O set não tem ordem nem índice: não dá pra fazer especies[0]. Em compensação, é imbatível pra responder "quais valores DISTINTOS existem aqui?".

set

Set de objetos exige __hash__

Pro set decidir se dois objetos são "o mesmo", a classe precisa de __eq__ e __hash__ — exatamente os métodos da aula 11.

set_de_objetos.py
class Tag:
    def __init__(self, nome):
        self.nome = nome

    def __eq__(self, outra):              # quando duas Tags são "iguais"? (aula 11)
        return self.nome == outra.nome

    def __hash__(self):                   # o set usa o hash pra detectar repetição
        return hash(self.nome)

    def __str__(self):
        return self.nome

# duas tags "vacinado" são consideradas a mesma → o set guarda só uma
tags = {Tag("vacinado"), Tag("castrado"), Tag("vacinado")}
print(len(tags))      # 2
📍 __eq__ e __hash__ foram a aula 11. Sem eles, o Python compara objetos por identidade (cada new é único) e o set NÃO removeria as duplicatas.

set

Operações de conjunto: | & -

Sets falam a linguagem da matemática: união, interseção e diferença com um operador cada.

operacoes_set.py
caes = {"Rex", "Thor", "Bidu"}
vacinados = {"Rex", "Mimi"}

print(caes | vacinados)   # união: todos, sem repetir
# {'Rex', 'Thor', 'Bidu', 'Mimi'}   (a ordem pode variar)

print(caes & vacinados)   # interseção: só quem está nos dois
# {'Rex'}

print(caes - vacinados)   # diferença: cães que NÃO estão em vacinados
# {'Thor', 'Bidu'}   (a ordem pode variar)
União | (junta tudo), interseção & (o que é comum) e diferença - (o que está num e não no outro). Como o set não tem ordem, a ordem impressa pode variar de máquina pra máquina.

ordenar

Ordenar objetos — o problema

Tentar ordenar uma lista de objetos direto não funciona: o Python não sabe POR QUAL atributo ordenar.

ordenar_problema.py
class Pet:
    def __init__(self, nome, idade):
        self.nome = nome
        self.idade = idade

pets = [Pet("Thor", 7), Pet("Rex", 4), Pet("Mimi", 2)]

# tentar ordenar objetos direto NÃO funciona: o Python não sabe o critério
pets.sort()
# TypeError: '<' not supported between instances of 'Pet' and 'Pet'
Números e strings o Python sabe comparar (1 < 2, "a" < "b"). Mas dois Pets? Por idade? Por nome? Ele não adivinha — precisamos DIZER o critério. É o que o próximo slide faz.

ordenar

sorted com key=lambda

O key= diz qual atributo usar como critério. lambda é uma mini-função de uma linha que extrai esse atributo.

sorted_key.py
class Pet:
    def __init__(self, nome, idade):
        self.nome = nome
        self.idade = idade
    def __str__(self):
        return f"{self.nome} ({self.idade} anos)"

pets = [Pet("Thor", 7), Pet("Rex", 4), Pet("Mimi", 2)]

# lambda = função anônima de 1 linha. lambda pet: pet.idade
# significa "dado um pet, devolva pet.idade" — é o CRITÉRIO de ordenação.
por_idade = sorted(pets, key=lambda pet: pet.idade)
for pet in por_idade:
    print(pet)
# Mimi (2 anos)
# Rex (4 anos)
# Thor (7 anos)

# reverse=True ordena do maior pro menor
mais_velhos = sorted(pets, key=lambda pet: pet.idade, reverse=True)
print([p.nome for p in mais_velhos])   # ['Thor', 'Rex', 'Mimi']
Pra ordenar por nome em vez de idade, é só trocar o critério: key=lambda pet: pet.nome. O lambda é só uma forma curta de escrever "de cada objeto, pegue ESTE atributo".

ordenar · a armadilha

sorted() vs .sort()

Dois jeitos de ordenar, com comportamentos bem diferentes. Confundir os dois gera a pegadinha clássica do None.

sorted() — devolve lista nova

sorted.py
numeros = [3, 1, 2]
novos = sorted(numeros)
print(novos)        # [1, 2, 3]
print(numeros)      # [3, 1, 2]
# a original fica INTACTA;
# o resultado é uma lista nova.

.sort() — in-place, devolve None

sort.py
numeros = [3, 1, 2]
resultado = numeros.sort()
print(numeros)      # [1, 2, 3]
print(resultado)    # None
# .sort() ordena a própria lista
# e devolve None — NÃO faça
# x = lista.sort()!
Regra: sorted(lista) quando quer uma cópia ordenada sem mexer na original; lista.sort() quando quer mudar a própria lista. A pegadinha mortal é x = lista.sort() — x vira None.

quando usar cada uma

Recapitulando as 4 coleções com objetos

item detalhe
list — quando a ORDEM importa Vários objetos numa sequência; aceita repetidos; percorre com for; busca por nome com for+if.
dict — quando há uma CHAVE natural Cada objeto tem um id/código/matrícula; busca direta com .get(chave); percorre com .items().
set — quando quer DISTINTOS Eliminar repetição (espécies, gêneros, tags); operações | & -; exige __eq__/__hash__ pra objetos.
tuple — quando os dados são FIXOS Imutável: coordenadas, RGB, registros que não mudam. Garante que ninguém altere por engano.

ao vivo · vamos construir juntos

Exercício ao Vivo: Repositório de Produtos

Vou montar esse na frente de vocês, do zero. Objetivo: uma lista de Produto que a gente sabe buscar pelo nome, filtrar por preço, ordenar com sorted(key=lambda) e listar as categorias distintas com set. Acompanhem o raciocínio passo a passo.

1

Monte a classe Produto e a lista

Com nome, preco e categoria, e um __str__ formatado (ex.: Mouse — R$ 80.00 (Informática)). Crie uma lista com 5 produtos.

2

Buscar e filtrar

Uma função buscar(lista, nome) que devolve o objeto ou None; e uma comprehension que filtra só os produtos até R$ 200.

3

Ordenar por preço

sorted(produtos, key=lambda p: p.preco) pra listar do mais barato pro mais caro — sem alterar a lista original.

4

Categorias distintas com set

Um set(p.categoria for p in produtos) pra descobrir quantas categorias diferentes existem no catálogo.

resolução · passo 1

A classe Produto e a lista

Começamos pela classe: três atributos e um __str__ que já entrega o produto formatado. E a lista com cinco itens.

📌
:.2f formata o preço com 2 casas decimais.
O __str__ (aula 03) deixa cada produto pronto pro print() — a regra de exibição mora na classe.
repositorio_produtos.py
class Produto:
    def __init__(self, nome, preco, categoria):
        self.nome = nome
        self.preco = preco
        self.categoria = categoria

    def __str__(self):
        return f"{self.nome} — R$ {self.preco:.2f} ({self.categoria})"

produtos = [
    Produto("Notebook", 3500.0, "Informática"),
    Produto("Mouse", 80.0, "Informática"),
    Produto("Cadeira", 750.0, "Móveis"),
    Produto("Mesa", 1200.0, "Móveis"),
    Produto("Teclado", 150.0, "Informática"),
]

for produto in produtos:
    print(produto)
# Notebook — R$ 3500.00 (Informática)
# Mouse — R$ 80.00 (Informática)
# Cadeira — R$ 750.00 (Móveis)
# Mesa — R$ 1200.00 (Móveis)
# Teclado — R$ 150.00 (Informática)

resolução · passo 2

Buscar e filtrar

Uma função de busca que devolve o objeto ou None, e uma comprehension que filtra por preço.

📌
buscar() percorre com for, compara o atributo e devolve o objeto ao achar — ou None no fim.
A comprehension [p for p in produtos if p.preco <= 200] lê-se: "os produtos cujo preço é até 200".
repositorio_produtos.py
# BUSCAR um produto pelo nome (devolve o objeto ou None)
def buscar(lista, nome):
    for produto in lista:
        if produto.nome == nome:
            return produto
    return None

print(buscar(produtos, "Mouse"))      # Mouse — R$ 80.00 (Informática)
print(buscar(produtos, "Geladeira"))  # None

# FILTRAR com comprehension: só os produtos até R$ 200
baratos = [p for p in produtos if p.preco <= 200]
print([p.nome for p in baratos])      # ['Mouse', 'Teclado']

resolução · passos 3 e 4 · saída esperada

Ordenar por preço e contar categorias

Fechamos com sorted(key=lambda) pra ordenar por preço e um set pra contar as categorias distintas.

📌
key=lambda p: p.preco diz "ordene comparando o preço de cada produto".
Mesmo com 5 produtos, o set revela só 2 categorias: Informática e Móveis.
repositorio_produtos.py
# ORDENAR por preço (do mais barato pro mais caro)
por_preco = sorted(produtos, key=lambda p: p.preco)
for produto in por_preco:
    print(produto)
# Mouse — R$ 80.00 (Informática)
# Teclado — R$ 150.00 (Informática)
# Cadeira — R$ 750.00 (Móveis)
# Mesa — R$ 1200.00 (Móveis)
# Notebook — R$ 3500.00 (Informática)

# categorias distintas, sem repetição, usando set
categorias = set(p.categoria for p in produtos)
print(len(categorias))   # 2
É a foto da aula inteira num exemplo só: lista de objetos, busca, comprehension pra filtrar, sorted(key=lambda) pra ordenar e set pra deduplicar. O sorted não alterou a lista produtos original.

recapitulando

Glossário rápido de hoje

item detalhe
list / tuple / dict / set Ordenada mutável [ ] / ordenada imutável ( ) / chave→valor { } / distintos sem ordem set( ).
list comprehension [expressão for item in coleção if condição] — cria uma lista nova transformando/filtrando.
lambda Função anônima de uma linha: lambda obj: obj.atributo. Usada como critério no key=.
sorted(lista, key=...) Devolve uma lista NOVA ordenada pelo critério do key=; aceita reverse=True.
lista.sort() Ordena a própria lista (in-place) e devolve None. Não faça x = lista.sort().
dict.get(chave) Busca segura: devolve None (ou um padrão) se a chave não existir. Evita o KeyError do [ ].

O que dominamos hoje

  • Guardo vários objetos numa list e processo todos com um for, em vez de variáveis soltas.
  • Uso o dict como repositório: a chave aponta direto pro objeto, e busco com .get() em vez de [ ].
  • Uso o set pra eliminar repetição, e sei que objetos no set precisam de __eq__ e __hash__ (aula 11).
  • Escrevo list comprehension pra transformar e filtrar coleções em uma linha legível.
  • Ordeno objetos com sorted(lista, key=lambda obj: obj.atributo), inclusive com reverse=True.
  • Sei a diferença entre sorted() (lista nova) e .sort() (in-place, devolve None).

exercícios · visão geral

Mãos à obra: os exercícios

Cinco exercícios em três níveis. Começamos juntos agora, em sala — quem não fechar todos, termina em casa. Mire pelo menos um de cada nível antes da próxima aula.

01

Fáceis

2 exercícios — Catálogo de filmes e Agenda telefônica. Foco: lista de objetos + comprehension, e dict com .get() e .items().

02

Médios

2 exercícios — Repositório de Alunos e Ranking de jogadores. Foco: dict-repositório + comprehension, e sorted(key=lambda).

03

Desafio

1 exercício — Catálogo de músicas com tags únicas. Foco: juntar lista + comprehension + set (com __hash__/__eq__) + ordenação.

exercícios · nível fácil

Para fixar listas, dict e comprehension

01

Catálogo de filmes

Crie a classe Filme com titulo, genero e ano, e um __str__ que mostre algo como Matrix (Ação, 1999). Monte uma lista com 5 ou mais filmes e: (a) imprima todos com um for; (b) use uma comprehension pra criar uma lista só com os títulos; (c) use uma comprehension com if pra pegar só os filmes de 2000 em diante. Foco: lista de objetos + comprehension pra transformar e filtrar.

02

Agenda telefônica

Monte um dicionário agenda que mapeia nome → telefone, com 4 contatos. Depois: (a) imprima o telefone de um contato com agenda[nome]; (b) busque um nome que NÃO está na agenda usando .get() e mostre que ele devolve None (sem estourar); (c) percorra a agenda inteira com for nome, telefone in agenda.items() imprimindo cada par. Foco: dict como repositório, .get() vs [ ], e .items().

exercícios · nível médio

Repositório e ordenação de objetos

03

Repositório de Alunos

Classe Aluno com matricula, nome e media (float) e um __str__ formatado. Classe Repositorio que guarda os alunos num dict por matrícula, com: adicionar(aluno) (insere usando a matrícula como chave); buscar(matricula) que devolve o aluno ou None (use .get()); e aprovados() que devolve, via comprehension sobre .values(), a lista de alunos com média ≥ 6.0. Teste com 5 alunos e imprima os aprovados. Foco: dict-repositório + comprehension sobre os valores do dict.

04

Ranking de jogadores

Classe Jogador com nome e pontos (int) e um __str__. Monte uma lista com 6 jogadores e, usando sorted com key=lambda: (a) ordene do maior pro menor em pontos (reverse=True); (b) ordene em ordem alfabética por nome. Ao final, imprima a lista original e mostre que o sorted não a alterou. Foco: sorted(key=lambda), reverse, e a diferença entre sorted() e .sort().

exercícios · nível desafio

O desafio que junta tudo

05

Catálogo de músicas com tags únicas

Classe Musica com titulo, artista e genero, um __str__ e os métodos __eq__/__hash__ que considerem duas músicas iguais quando têm o mesmo (titulo, artista) — assim o set elimina repetidas. Classe Catalogo que guarda uma lista de músicas, com: adicionar(musica); por_genero(g) que devolve, via comprehension, só as músicas de um gênero; generos_disponiveis() que devolve um set com os gêneros distintos; e top_artistas() que devolve um set com os artistas distintos. Bônus: um método que devolve a lista ordenada por artista com sorted(key=lambda m: m.artista). Teste adicionando 6 músicas (com pelo menos uma repetida) e confirme que o set elimina a repetição. Foco: juntar lista + comprehension + set com __hash__/__eq__ + ordenação numa coisa só.

próxima aula

Aula 19 · 23/06

Introdução à UML aplicada ao Python

Hoje organizamos objetos em coleções. Na próxima, damos um passo atrás: vamos DESENHAR as classes e suas relações ANTES de codar — o mapa antes da viagem.

diagrama de classes ler e escrever UML UML → Python