Lógica de Programação

Coleções em Python

Aula interativa Prof. Raul de Araújo Lima · Sistemas de Informação · UniCatólica

Python carregando…

Strings, listas, matrizes, tuplas e dicionários

Até agora cada variável guardou um único valor. Hoje vamos guardar vários valores sob um mesmo nome e aprender a escolher a estrutura certa para cada situação.

Navegação: ← → trocam de etapa · V alterna entre etapas e página única · M sumário · F tela cheia · + − tamanho do texto · dentro do código, Ctrl+Enter executa.

Todo código desta aula pode ser editado e executado aqui mesmo. Altere os exemplos à vontade; o botão ↺ restaura o original. Suas alterações ficam salvas neste navegador; em Progresso você pode baixá-las em um arquivo e continuar em outro computador.

Nos desafios e exercícios, o botão ✓ Verificar testa seu código com várias entradas e mostra o que está certo e o que falta.

Por que precisamos de coleções?

Imagine guardar as notas de uma turma de 40 alunos. Com o que vimos até agora, seriam 40 variáveis: nota1, nota2, …, nota40.

Para calcular a média, precisaríamos escrever todas elas na conta. E se a turma tiver 41 alunos amanhã?

Uma coleção guarda vários valores sob um único nome. O programa passa a funcionar para qualquer quantidade de dados.

Antes de executar, pergunte à turma: qual das duas versões continuaria funcionando com mil notas sem alterar nenhuma linha de cálculo?
len([7, 8, 6]) → 3sum([7, 8, 6]) → 21

Strings: texto é uma sequência

Você já usa strings desde a primeira aula. A novidade de hoje: uma string é uma sequência de caracteres, em ordem, e podemos acessar cada um deles.

Podemos criar strings com aspas simples, duplas ou triplas (para várias linhas). O resultado é o mesmo tipo: str.

A função len() devolve o tamanho de uma sequência, ou seja, quantos elementos ela tem. Espaços também contam.

len("casa") → 4len("a b") → 3len("") → 0

Índices: a posição de cada caractere

Cada caractere ocupa uma posição numerada. A contagem começa em 0. Também dá para contar de trás para frente com índices negativos: -1 é o último.

Para acessar um caractere: texto[posição].

Se a string tem tamanho n, os índices válidos vão de 0 até n - 1 (ou de -n até -1).

A última linha do exemplo pede o índice 6 de uma string com 6 caracteres. Peça para a turma prever o que vai acontecer antes de executar.

Fatiamento: pedaços de uma sequência

texto[início:fim:passo] devolve um pedaço. O início entra, o fim fica de fora. Qualquer parte pode ser omitida.

OmitidoValor assumido
iníciocomeço da sequência
fimaté o final
passo1 (de um em um)

Passo negativo percorre de trás para frente. Por isso s[::-1] inverte a string.

Operadores e percurso com for

OperadorO que fazExemplo
+junta (concatena)"ab" + "cd" → "abcd"
*repete"ab" * 3 → "ababab"
inverifica se está contido"as" in "casa" → True
not inverifica se não está"x" not in "casa" → True

O for percorre uma sequência elemento por elemento. Em uma string, a variável do laço recebe um caractere por vez.

Métodos de string

Um método é uma ação que o próprio valor sabe executar. Escrevemos o valor, um ponto e o nome da ação com parênteses: texto.upper().

Métodos de string devolvem uma string nova. A original continua igual; para guardar o resultado, use uma variável.

MétodoExemploResultado
upper() / lower()"Oi".upper()"OI"
strip()" oi ".strip()"oi"
replace(a, b)"gato".replace("g", "p")"pato"
count(x)"banana".count("a")3
find(x)"banana".find("n")2 (ou -1)
startswith(x)"Python".startswith("Py")True
isdigit()"2026".isdigit()True

Construindo strings: o padrão acumulador

Como strings não mudam, para “montar” um texto começamos com a string vazia "" e vamos juntando pedaços. É o mesmo padrão do acumulador numérico, agora com texto.

letra + invertida coloca a letra nova na frente; invertida + letra colocaria atrás e copiaria a palavra igual.

Com um if dentro do laço, escolhemos quais caracteres entram no resultado (um filtro) ou quantos atendem a uma condição (um contador).

"a".isupper() → False"A".isupper() → True"7".isdigit() → True
Experimente: troque cada espaço da frase por "_" sem usar replace().

Tratando o texto digitado

Pessoas digitam de jeitos diferentes: "Sim", " sim ", "SIM". Antes de comparar, padronize o texto.

ProblemaSolução
espaços sobrando nas pontas.strip()
maiúsculas e minúsculas misturadas.lower()
texto que deveria ser númerotestar .isdigit() antes do int()

Métodos podem ser encadeados: cada um age sobre o resultado do anterior, da esquerda para a direita.

" SIM ".strip().lower() → 'sim'
isdigit() só aceita dígitos: "-5".isdigit() e "3.5".isdigit() dão False.

split e join: da string para a lista e de volta

split() quebra uma string em pedaços e devolve uma lista. Sem argumento, separa pelos espaços.

join() faz o caminho inverso: junta os itens de uma lista usando a string como separador.

"a,b,c".split(",") → ['a', 'b', 'c']"-".join(['a', 'b']) → 'a-b'int("10") → 10
Este é o jeito mais comum de ler vários valores digitados na mesma linha. Os pedaços continuam sendo texto: converta com int() ou float() antes de fazer contas.

Strings são imutáveis

Não é possível alterar um caractere de uma string existente. Para “modificar” um texto, criamos uma string nova a partir da antiga.

Tentativa de alterar

Criando uma nova string

Reatribuir a variável (palavra = ...) é diferente de alterar a string: a variável passa a apontar para outro texto. Guarde esta ideia; ela volta em listas e tuplas.

Desafio: vogais e palíndromo

  1. Conte quantas vogais existem na frase.
  2. Verifique se a frase é um palíndromo, isto é, se é lida igual de trás para frente. Ignore espaços e diferenças entre maiúsculas e minúsculas.

Ferramentas úteis: for, in, lower(), replace() e [::-1].

"o" in "aeiou" → True"ovo"[::-1] → 'ovo'
Mostrar uma solução

Listas

Uma lista guarda vários valores em ordem, entre colchetes [ ] e separados por vírgula. Os valores podem ser de qualquer tipo, inclusive misturados.

Tudo o que vimos em strings vale aqui: índices, índices negativos, fatiamento, len(), in e percurso com for.

Listas são mutáveis

Diferente das strings, uma lista pode ser alterada depois de criada: trocar, incluir e remover elementos.

OperaçãoO que faz
lista[i] = xtroca o elemento da posição i
lista.append(x)adiciona x no final
lista.insert(i, x)adiciona x na posição i
lista.remove(x)remove a primeira ocorrência do valor x
lista.pop()remove o último e devolve o valor removido
lista.pop(i)remove a posição i e devolve o valor
del lista[i]remove pela posição

Mais operações com listas

OperaçãoO que faz
a + bnova lista com os elementos de a e de b
[0] * 5nova lista repetindo os elementos
a.extend(b)acrescenta todos os elementos de b em a
a.count(x)quantas vezes x aparece
a.index(x)posição da primeira ocorrência (erro se não existir)
a.reverse()inverte a própria lista
a.clear()esvazia a lista
append(b) acrescenta b como um elemento (uma lista dentro da lista); extend(b) acrescenta cada elemento de b.

Percorrendo e resumindo listas

max([3, 9, 4]) → 9min([3, 9, 4]) → 3sorted([3, 1, 2]) → [1, 2, 3]list(range(3)) → [0, 1, 2]

Quando precisamos da posição, percorremos os índices com range(len(lista)):

sorted(lista) cria uma lista nova; lista.sort() altera a própria lista e não devolve nada.

Busca em listas

Buscar é percorrer a lista comparando cada elemento com o que procuramos. Quando achar, guardamos a posição e paramos com break. Se nunca achar, a posição continua -1.

Uma variação importante: em vez de procurar um valor conhecido, procurar a posição do maior. Guardamos o índice do melhor até agora e trocamos quando aparece alguém maior.

Com duas listas paralelas (mesma posição = mesmo registro), a posição encontrada em uma serve para consultar a outra.

Esse raciocínio é a base da aula de Ordenação e Busca. in, index() e max() fazem exatamente isso por dentro.

Construindo listas com laços

Padrão muito comum: começar com uma lista vazia e ir acrescentando com append() dentro de um laço.

O operador % devolve o resto da divisão. Um número é par quando o resto da divisão por 2 é zero.

7 % 2 → 18 % 2 → 0list(range(1, 6)) → [1, 2, 3, 4, 5]

No segundo exemplo, os valores digitados podem ser escritos no campo Entrada, um por linha, antes de executar. Se o campo estiver vazio, o navegador abre uma caixa para digitar.

Extra: a forma compacta (compreensão de lista)

Cuidado: dois nomes, uma lista

b = a não copia a lista. As duas variáveis passam a apontar para a mesma lista na memória; alterar por um nome altera o que o outro enxerga.

a b 1 2 3 4 uma única lista na memória

Para obter uma lista independente, use a.copy() (ou a[:]).

Com strings esse problema não aparece: como elas são imutáveis, nenhuma operação altera o texto compartilhado.

Desafio: notas da turma

  1. Calcule e mostre a média da turma.
  2. Monte uma nova lista apenas com as notas acima da média.
  3. Mostre quantos alunos foram aprovados (nota maior ou igual a 7).

round(valor, casas) arredonda um número.

round(7.2142, 2) → 7.21round(3.14159, 1) → 3.1
Mostrar uma solução

Matrizes: listas de listas

Uma matriz é uma lista em que cada elemento é outra lista: uma linha. Para chegar a um valor usamos dois índices: m[linha][coluna].

m[1] é a segunda linha inteira (uma lista). m[1][2] é o terceiro valor dessa linha.

len(m) é o número de linhas; len(m[0]), o número de colunas.

Matrizes aparecem em tabuleiros (jogo da velha, xadrez), planilhas, notas de alunos por avaliação, assentos de um cinema e imagens (cada pixel é uma posição).

Percorrendo matrizes

Percorrer uma matriz pede dois laços aninhados: o de fora anda pelas linhas e o de dentro pelas colunas de cada linha.

QueremosComo
uma linha im[i] (já é uma lista: sum(m[i]))
uma coluna jpercorrer as linhas pegando m[i][j]
a diagonal principalm[i][i]
todos os valoresfor linha in m: + for valor in linha:
print(5, end="\t") → separa com tabulação

Criando matrizes (e uma armadilha)

Para criar uma matriz de tamanho conhecido, montamos uma lista nova para cada linha dentro de um laço.

Atalho perigoso: [[0] * 4] * 3 não cria três linhas, e sim três nomes para a mesma linha, como no slide “Cuidado: dois nomes, uma lista”. Alterar uma altera todas.

Para ler uma matriz do teclado, cada linha pode ser digitada de uma vez, com os valores separados por espaço, e quebrada com split().

Extra: a forma compacta

Desafio: jogo da velha

Leia as três linhas de um tabuleiro de jogo da velha, com as casas separadas por espaço (- é casa vazia).

  1. Mostre o tabuleiro em forma de grade, como X | O | X.
  2. Verifique se alguém venceu em uma linha, coluna ou diagonal e mostre X venceu, O venceu ou Ninguém venceu.
" | ".join(["X", "O", "X"]) → 'X | O | X'a == b == c == "X" → as três são X?

São 8 formas de vencer: 3 linhas, 3 colunas e 2 diagonais.

Mostrar uma solução

Tuplas

Uma tupla é uma sequência como a lista, escrita entre parênteses ( ). A diferença: é imutável. Depois de criada, não ganha, não perde e não troca elementos.

Use tuplas para dados que andam juntos e não devem mudar: coordenadas, data (dia, mês, ano), dias da semana.

Tupla com um único elemento precisa de vírgula: (42,). Sem a vírgula, (42) é apenas o número 42 entre parênteses.

Desempacotamento

Podemos distribuir os elementos de uma tupla em várias variáveis de uma só vez. A quantidade de variáveis precisa ser igual à quantidade de elementos.

Isso permite trocar o valor de duas variáveis sem usar uma variável auxiliar e percorrer listas de pares de forma legível.

enumerate() entrega pares (posição, elemento) durante o for.

list(enumerate(["a", "b"])) → [(0, 'a'), (1, 'b')]

zip e tuplas como registros

zip(a, b) percorre duas sequências lado a lado, entregando a cada volta uma tupla com um elemento de cada. É o jeito mais limpo de trabalhar com listas paralelas.

list(zip(["a", "b"], [1, 2])) → [('a', 1), ('b', 2)]

Se as listas tiverem tamanhos diferentes, zip para na menor.

Tuplas também funcionam como pequenos registros de tamanho fixo, em que cada posição tem um significado: (dia, mês, ano), (nome, nota), (x, y).

(1, 2, 2, 3).count(2) → 2("a", "b").index("b") → 1

Lista ou tupla?

ListaTupla
Sintaxe[1, 2, 3](1, 2, 3)
Pode mudar?simnão
Índices e fatiamentosimsim
append, remove…simnão existem
Uso típicocoleção que cresce ou é editada: carrinho, fila, notasregistro fixo: coordenada, data, configurações

Se precisar alterar uma tupla, converta para lista com list(), altere e, se quiser, volte com tuple().

Dicionários

Em listas e tuplas acessamos os valores pela posição. Em um dicionário, cada valor tem um nome: a chave. Escrevemos pares chave: valor entre chaves { }.

"nome"→"Ana" "matricula"→2026001 "curso"→"Sistemas de Informação"

As chaves não se repetem e normalmente são strings ou números. Os valores podem ser qualquer coisa, inclusive listas.

Acessar uma chave que não existe com colchetes gera erro. get() devolve None (ou um valor padrão) em vez de erro.

Alterando um dicionário

OperaçãoO que faz
d[chave] = valorchave nova: adiciona; chave existente: altera
del d[chave]remove o par
d.pop(chave)remove e devolve o valor
chave in dverifica se a chave existe
len(d)quantidade de pares
in procura apenas nas chaves. Para procurar entre os valores, use valor in d.values().

Percorrendo dicionários

FormaA cada volta, recebe
for k in d:uma chave
for v in d.values():um valor
for k, v in d.items():uma tupla (chave, valor), desempacotada

Na f-string, :.2f mostra o número com duas casas decimais.

f"{4.5:.2f}" → '4.50'

Dicionário como contador

Problema clássico: quantas vezes cada palavra aparece em um texto? A chave é a palavra; o valor é a contagem.

A cada palavra: se ela já está no dicionário, somamos 1; se não está, ela entra com valor 1.

A versão curta usa get(chave, 0): devolve o valor atual, ou 0 se a chave ainda não existir.

{"a": 2}.get("a", 0) → 2{"a": 2}.get("b", 0) → 0

Agrupando e consultando com dicionários

Agrupar: o valor de cada chave pode ser uma lista. A cada item, se a chave ainda não existe, criamos a lista vazia; depois, acrescentamos o item na lista daquela chave.

Consultar: um dicionário também substitui longas cadeias de if/elif que só traduzem um valor em outro.

sorted(d) devolve as chaves em ordem, útil para exibir o resultado organizado.

sorted({"b": 1, "a": 2}) → ['a', 'b']

Estruturas combinadas

As estruturas podem ser combinadas. Uma lista de dicionários representa bem uma tabela: cada dicionário é uma linha (um aluno) e cada chave é uma coluna.

Para chegar a um valor interno, encadeamos os acessos da esquerda para a direita:

turma[2]["notas"][0]
terceiro aluno → suas notas → primeira nota.

Desafio: vendas da cantina

A lista abaixo registra vendas como tuplas (produto, quantidade). Um mesmo produto aparece várias vezes.

  1. Monte um dicionário com o total vendido de cada produto.
  2. Mostre cada produto com seu total.
  3. Descubra qual produto vendeu mais.

Este desafio usa as quatro estruturas da aula.

Mostrar uma solução

Comparativo das estruturas

EstruturaSintaxeAcessoPode mudar?Quando usar
String"abc"posiçãonãotexto
Lista[1, 2, 3]posiçãosimcoleção ordenada que cresce, diminui ou é editada
Matriz[[1, 2], [3, 4]]linha e colunasimdados em grade: tabuleiros, tabelas, notas por avaliação
Tupla(1, 2, 3)posiçãonãogrupo fixo de valores relacionados
Dicionário{"k": 1}chavesimassociar um identificador a um valor

Qual estrutura usar?

Leia a situação para a turma, colete as respostas e só então clique.

Qual será a saída?

Leia o código, escreva sua resposta e só então clique. Errou? Copie o código para o laboratório e execute linha por linha.

Prática 1: strings e listas

Escreva sua solução no editor. ▶ Executar roda com a entrada que você quiser; ✓ Verificar roda os testes automáticos e mostra o que falta. Tente antes de abrir a solução!

1. Analisando uma frase básico

Leia uma frase e mostre quantas palavras ela tem e qual é a maior palavra. Em caso de empate, mostre a primeira.

EntradaSaída esperada
python é uma linguagem legal
Palavras: 5
Maior palavra: linguagem
Mostrar uma solução

2. Sem repetidos básico

Leia números inteiros digitados na mesma linha, separados por espaço. Mostre a lista sem números repetidos, mantendo a ordem em que apareceram pela primeira vez.

EntradaSaída esperada
3 1 3 2 1 5 2 5
Sem repetidos: [3, 1, 2, 5]
Mostrar uma solução

Prática 2: strings e tuplas

3. Iniciais do nome intermediário

Leia um nome completo e mostre as iniciais em maiúsculas, ignorando as palavras da, de, do, das, dos e e.

EntradaSaída esperada
Maria da Silva Costa
Iniciais: M. S. C.
joão dos santos
Iniciais: J. S.
Mostrar uma solução

4. Nome do mês intermediário

Guarde os nomes dos meses em uma tupla. Leia um número e mostre o nome do mês. Para números fora de 1 a 12, mostre Mês inválido.

EntradaSaída esperada
3
Mês: março
13
Mês inválido
Teste também com 0. Por que meses[0 - 1] mostraria dezembro em vez de dar erro?
Mostrar uma solução

Prática 3: dicionários e matrizes

5. Agenda telefônica desafio

Use um dicionário nome → telefone e um menu com while:

OpçãoAçãoMensagens
1adicionar: lê nome e telefoneContato salvo
2buscar: lê um nomeEncontrado: 9999-1111 ou Contato não encontrado
3remover: lê um nomeContato removido ou Contato não encontrado
4listar em ordem alfabéticaAna - 9999-1111, um por linha, ou Agenda vazia
0sair

Qualquer outra opção mostra Opção inválida.

Mostrar uma solução

6. Diagonal e maior valor desafio

Leia o tamanho n de uma matriz quadrada e depois suas n linhas (valores separados por espaço). Mostre a soma da diagonal principal e o maior valor da matriz.

EntradaSaída esperada
3
1 2 3
4 5 6
7 8 9
Diagonal: 15
Maior: 9

Os testes incluem uma matriz só com negativos: cuidado com o valor inicial do maior.

Mostrar uma solução

Laboratório livre

Espaço para testar ideias durante a aula. Sugestões: conte quantas vezes cada letra aparece em seu nome; monte uma matriz 5 × 5 com a tabuada; guarde um cardápio em um dicionário e calcule o valor de um pedido.