Capítulo 6 — Listas e strings
Até agora, nossas variáveis guardam um valor por vez: um número, um texto, um booleano. Mas imagine que você quer armazenar os nomes de todos os alunos da sua turma. Criar uma variável para cada nome (aluno1 = "Ana", aluno2 = "Bruno", ... aluno30 = "Zoe") seria absurdo. Seria impraticável, confuso e impossível de trabalhar quando a quantidade de dados cresce.
É aí que entram as listas. Uma lista é um "container" — um recipiente que guarda vários valores em uma única variável. E não só isso: listas nos permitem organizar dados, procurar por eles, modificá-los e iterar sobre eles (percorrer um por um) de forma elegante. A maioria dos programas que existem — desde apps de redes sociais até jogos — trabalham com listas o tempo inteiro.
Também vamos aprofundar nossos conhecimentos sobre strings (textos). Você vai descobrir que strings em Python são quase como listas também, e têm métodos muito úteis para manipular texto.
1. O que são listas?
Uma lista é uma coleção ordenada de elementos, guardados em uma única variável. Cada elemento pode ser um número, um texto, um booleano — qualquer coisa. Os elementos ficam em uma ordem específica, e cada um tem uma "posição" (que chamamos de índice) para a gente acessá-lo depois.
Criando listas: sintaxe com colchetes
A sintaxe é bem simples — use colchetes [ ] e separe os elementos com vírgulas:
nomes = ["Ana", "Bruno", "Carlos", "Diana"]
notas = [8.5, 9.0, 7.5, 10.0]
misturada = [1, "texto", 3.14, True] # pode ter tipos diferentes na mesma lista
vazia = [] # lista vazia — útil para começar a adicionar coisas depois
Bem fácil! A lista nomes tem 4 elementos, a notas também tem 4, a misturada tem 4 elementos de tipos diferentes, e a vazia não tem nada (por enquanto).
Você também pode criar listas usando a função list():
letras = list("ABC") # transforma a string "ABC" numa lista de caracteres
print(letras)
['A', 'B', 'C']
Mas o método com colchetes é muito mais comum e mais legível.
Listas de números, strings e mistas
Vamos ver exemplos práticos de cada tipo:
# Lista de números inteiros
números = [1, 2, 3, 4, 5]
# Lista de números decimais
preços = [9.90, 14.50, 3.20, 120.00]
# Lista de strings (textos)
frutas = ["maçã", "banana", "laranja", "morango"]
# Lista mista — tem vários tipos
info_pessoa = ["João", 25, 1.75, True] # nome, idade, altura, está vivo?
# Lista com listas dentro (ainda não vamos aprofundar nisso)
matrix = [[1, 2, 3], [4, 5, 6]]
Repare na última: é perfeitamente legal ter uma lista dentro de outra. Mas deixemos isso para depois.
Lista vazia e por que ela é útil
A lista vazia [] parece inútil à primeira vista — afinal, não tem nada nela! Mas é muito útil quando você quer começar com uma lista e adicionar coisas nela conforme o programa executa:
compras = [] # começa vazia
print(f"Lista antes: {compras}")
# Mais para frente no programa, você adiciona coisas
compras = compras + ["leite"] # agora tem 1 elemento
compras = compras + ["pão", "queijo"] # agora tem 3 elementos
print(f"Lista depois: {compras}")
Lista antes: []
Lista depois: ['leite', 'pão', 'queijo']
Veremos melhor como adicionar elementos com append() na seção de modificação. Por enquanto, apenas saiba que é comum começar com [] e ir adicionando.
2. Acessando elementos
Você criou uma lista, mas como pega um elemento específico dela? Usa o índice — a posição do elemento. Mas cuidado: em Python, a contagem começa em zero, não em um!
Índices começam em 0!
frutas = ["maçã", "banana", "laranja", "morango"]
A lista frutas tem 4 elementos:
- Índice 0: "maçã"
- Índice 1: "banana"
- Índice 2: "laranja"
- Índice 3: "morango"
Para acessar um elemento, coloque o índice entre colchetes:
frutas = ["maçã", "banana", "laranja", "morango"]
print(frutas[0]) # "maçã"
print(frutas[1]) # "banana"
print(frutas[2]) # "laranja"
print(frutas[3]) # "morango"
maçã
banana
laranja
morango
Essa é a parte mais importante: não esqueça de começar em zero! Muita gente confunde e tenta acessar frutas[1] esperando pegar "maçã", mas não — frutas[1] é "banana". Este é um dos erros mais comuns e divertidos da programação.
numeros = [10, 20, 30, 40, 50]
# Simulando o acesso:
# numeros[0] → 10
# numeros[1] → 20
# numeros[2] → 30
# numeros[3] → 40
# numeros[4] → 50
Índices negativos: acessando do final para o início
Python tem um truque legal: você pode usar índices negativos para contar de trás para frente! O índice -1 se refere ao último elemento, -2 ao penúltimo, e assim por diante:
frutas = ["maçã", "banana", "laranja", "morango"]
print(frutas[-1]) # "morango" (o último)
print(frutas[-2]) # "laranja" (o penúltimo)
print(frutas[-3]) # "banana"
print(frutas[-4]) # "maçã"
morango
laranja
banana
maçã
Isso é super útil! Imagine que você quer pegar o último item de uma lista e não sabe quantos elementos ela tem. Em vez de escrever lista[len(lista) - 1], você simplesmente escreve lista[-1]. Muito mais prático.
# Índices positivos: contam do início
# [0] [1] [2] [3]
# maçã banana laranja morango
# Índices negativos: contam do final
# [-4] [-3] [-2] [-1]
# maçã banana laranja morango
Erro comum: IndexError
Agora vem a parte do "o que não fazer". Se você tentar acessar um índice que não existe, o Python levanta um erro chamado IndexError:
frutas = ["maçã", "banana", "laranja"] # 3 elementos (índices 0, 1, 2)
print(frutas[3]) # ERRO! Índice 3 não existe.
Traceback (most recent call last):
File "...", line X
IndexError: list index out of range
A mensagem é clara: "list index out of range" — o índice está fora do alcance. Se a lista tem 3 elementos, os índices válidos são 0, 1 e 2. Tentar acessar 3 (ou 100, ou -10 se a lista não é tão grande) causa erro.
Por isso é importante: sempre saiba quantos elementos sua lista tem (use len(), que veremos em breve), ou use índices que você tem certeza de que existem.
3. Modificando listas
Listas são mutáveis — você pode mudar, adicionar e remover elementos. Vamos ver as operações mais comuns.
Alterando um elemento pelo índice
Para mudar um elemento, acesse por índice e atribua um novo valor:
notas = [7.0, 8.5, 6.0, 9.5]
print(f"Antes: {notas}")
notas[1] = 9.0 # muda a nota no índice 1 (8.5 vira 9.0)
print(f"Depois: {notas}")
Antes: [7.0, 8.5, 6.0, 9.5]
Depois: [7.0, 9.0, 6.0, 9.5]
Simples assim. Funciona também com índices negativos:
notas = [7.0, 8.5, 6.0, 9.5]
notas[-1] = 10.0 # muda o último elemento
print(notas)
[7.0, 8.5, 6.0, 10.0]
append() — adicionar ao final
O método append() adiciona um elemento ao final da lista:
compras = ["leite", "pão"]
print(f"Antes: {compras}")
compras.append("queijo")
compras.append("ovos")
print(f"Depois: {compras}")
Antes: ['leite', 'pão']
Depois: ['leite', 'pão', 'queijo', 'ovos']
Repare: append() modifica a lista original. Não retorna uma nova lista — ele muda a lista que você já tem. É como adicionar um item à sua lista de compras no caderno.
insert() — adicionar em posição específica
Se você quer adicionar um elemento em um lugar específico (não só no final), usa insert(). A sintaxe é lista.insert(índice, valor):
alunos = ["Ana", "Bruno", "Diana"]
print(f"Antes: {alunos}")
alunos.insert(1, "Carlos") # insere "Carlos" no índice 1
print(f"Depois: {alunos}")
Antes: ['Ana', 'Bruno', 'Diana']
Depois: ['Ana', 'Carlos', 'Bruno', 'Diana']
Repare que "Bruno" e "Diana" foram "empurrados" para a frente. O novo elemento vai no índice 1, e tudo que estava lá em diante se move.
alunos = ["Ana", "Bruno", "Diana"]
alunos.insert(0, "Zoe") # insere no início (índice 0)
print(alunos)
['Zoe', 'Ana', 'Bruno', 'Diana']
remove() e pop() — remover elementos
Existem dois jeitos de remover um elemento. O remove() remove a primeira ocorrência de um valor específico:
frutas = ["maçã", "banana", "laranja", "banana"]
frutas.remove("banana") # remove a primeira "banana"
print(frutas)
['maçã', 'laranja', 'banana']
Repare: mesmo que "banana" apareça duas vezes, remove() só tira a primeira.
Já o pop() remove um elemento pela sua posição (índice). E diferente de remove(), pop() retorna o elemento removido:
notas = [7.0, 8.5, 6.0, 9.5]
removida = notas.pop(1) # remove e retorna o elemento no índice 1
print(f"Lista: {notas}")
print(f"Removida: {removida}")
Lista: [7.0, 6.0, 9.5]
Removida: 8.5
Se você chamar pop() sem argumento, ele remove e retorna o último elemento:
notas = [7.0, 8.5, 6.0, 9.5]
ultima = notas.pop() # remove e retorna o último
print(f"Lista: {notas}")
print(f"Última: {ultima}")
Lista: [7.0, 8.5, 6.0]
Última: 9.5
sort() e sorted() — ordenar
Para ordenar uma lista, você tem duas opções. O método sort() ordena a lista no próprio lugar (modifica a lista original):
numeros = [5, 2, 8, 1, 9]
print(f"Antes: {numeros}")
numeros.sort()
print(f"Depois: {numeros}")
Antes: [5, 2, 8, 1, 9]
Depois: [1, 2, 5, 8, 9]
Já a função sorted() retorna uma nova lista ordenada, deixando a original intacta:
numeros = [5, 2, 8, 1, 9]
ordenada = sorted(numeros)
print(f"Original: {numeros}")
print(f"Ordenada: {ordenada}")
Original: [5, 2, 8, 1, 9]
Ordenada: [1, 2, 5, 8, 9]
Qual usar? sort() se você quer mudar a lista original. sorted() se você quer manter a original e criar uma nova ordenada.
Para ordenar em ordem decrescente, adicione reverse=True:
numeros = [5, 2, 8, 1, 9]
numeros.sort(reverse=True)
print(numeros)
[9, 8, 5, 2, 1]
Também funciona com strings:
nomes = ["Zoe", "Ana", "Bruno", "Carlos"]
nomes.sort()
print(nomes)
['Ana', 'Bruno', 'Carlos', 'Zoe']
len() — tamanho da lista
Para saber quantos elementos tem em uma lista, use len():
frutas = ["maçã", "banana", "laranja", "morango"]
print(f"A lista tem {len(frutas)} elementos")
A lista tem 4 elementos
Isso é útil quando você quer validar dados ou quando quer iterar (percorrer) uma lista e precisa saber quando para. len() funciona com qualquer sequência em Python — listas, strings, tuplas, etc.
4. Iterando sobre listas com for
Acessar elemento por elemento é útil, mas frequentemente você quer fazer a mesma coisa com cada elemento da lista. Para isso, usamos um for loop — que você viu no Capítulo 4!
for item in lista:
A forma mais simples e mais Pythônica:
frutas = ["maçã", "banana", "laranja"]
for fruta in frutas:
print(f"Eu gosto de {fruta}")
Eu gosto de maçã
Eu gosto de banana
Eu gosto de laranja
Na primeira volta do loop, fruta recebe "maçã". Na segunda, recebe "banana". E assim por diante até acabar a lista. É automático — o Python sabe quando parar.
Outro exemplo:
notas = [7.5, 8.0, 9.5, 6.0]
total = 0
for nota in notas:
total = total + nota
media = total / len(notas)
print(f"Média: {media}")
Média: 7.75
for i in range(len(lista)): — quando precisamos do índice
Às vezes, você precisa do índice além do valor. Por exemplo, quando quer exibir "Elemento 1: ...", "Elemento 2: ...". Para isso, use range(len(lista)):
frutas = ["maçã", "banana", "laranja"]
for i in range(len(frutas)):
print(f"Posição {i}: {frutas[i]}")
Posição 0: maçã
Posição 1: banana
Posição 2: laranja
range(len(frutas)) cria uma sequência de 0 até len(frutas) - 1. Como frutas tem 3 elementos, range(len(frutas)) é equivalente a range(3), que produz 0, 1, 2.
enumerate() — introdução breve
Python oferece uma forma ainda mais elegante quando você precisa tanto do índice quanto do valor: enumerate():
frutas = ["maçã", "banana", "laranja"]
for i, fruta in enumerate(frutas):
print(f"Posição {i}: {fruta}")
Posição 0: maçã
Posição 1: banana
Posição 2: laranja
enumerate() devolve pares (índice, valor), que você desempacota em i e fruta. É mais limpo e mais Pythônico que range(len(...)).
5. Fatiamento (slicing)
Slicing é uma técnica para extrair uma "fatia" de uma lista ou string. É super útil e super elegante.
lista[inicio:fim] e lista[inicio:fim:passo]
A sintaxe geral é lista[inicio:fim:passo]. Mas vamos começar simples com lista[inicio:fim]:
numeros = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(numeros[2:5]) # do índice 2 até 4 (5 não entra)
print(numeros[0:3]) # do índice 0 até 2
print(numeros[5:]) # do índice 5 até o final
print(numeros[:3]) # do início até o índice 2
print(numeros[:]) # cópia da lista inteira
[2, 3, 4]
[0, 1, 2]
[5, 6, 7, 8, 9]
[0, 1, 2]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Regra importante: fim não entra na fatia. É como um intervalo fechado à esquerda e aberto à direita: [inicio, fim).
Agora com o passo:
numeros = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(numeros[::2]) # do início ao fim, pulando de 2 em 2
print(numeros[1::2]) # começando do índice 1, pulando de 2 em 2
print(numeros[::-1]) # do fim ao início (invertido!)
[0, 2, 4, 6, 8]
[1, 3, 5, 7, 9]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Aquele numeros[::-1] é mágico: inverte a lista inteira! É uma forma elegante de reverter.
Funciona igual para strings!
Strings funcionam como listas de caracteres para fins de slicing:
palavra = "python"
print(palavra[0:3]) # "pyt"
print(palavra[::2]) # "pto"
print(palavra[::-1]) # "nohtyp"
pyt
pto
nohtyp
6. Métodos de string (aprofundamento)
Strings têm uma quantidade absurda de métodos úteis. Vamos ver os mais comuns e mais práticos.
upper(), lower(), capitalize(), title()
Para mudar maiúsculas e minúsculas:
texto = "Olá Mundo"
print(texto.upper()) # "OLÁ MUNDO"
print(texto.lower()) # "olá mundo"
print(texto.capitalize()) # "Olá mundo" (só a primeira letra maiúscula)
print(texto.title()) # "Olá Mundo" (primeira letra de cada palavra maiúscula)
OLÁ MUNDO
olá mundo
Olá mundo
Olá Mundo
strip(), lstrip(), rstrip()
Esses métodos removem espaços em branco do início e/ou fim de uma string:
texto = " olá mundo "
print(f"'{texto.strip()}'") # remove dos dois lados
print(f"'{texto.lstrip()}'") # remove só da esquerda (left)
print(f"'{texto.rstrip()}'") # remove só da direita (right)
'olá mundo'
'olá mundo '
' olá mundo'
Isso é muito útil quando você lê dados do usuário. Às vezes vem espaço extra que atrapalha:
nome = input("Qual seu nome? ") # usuario digita " Ana " com espaços
nome = nome.strip() # agora nome é "Ana" sem espaços
print(f"Bem-vinda, {nome}!")
split() e join()
split() divide uma string em várias partes, usando um separador:
frase = "Eu gosto de programar"
palavras = frase.split() # sem argumento, usa espaço como separador
print(palavras)
['Eu', 'gosto', 'de', 'programar']
Pode especificar outro separador:
csv = "Ana,25,São Paulo"
dados = csv.split(",")
print(dados)
['Ana', '25', 'São Paulo']
join() faz o oposto — junta uma lista de strings usando um separador:
palavras = ["Eu", "gosto", "de", "programar"]
frase = " ".join(palavras) # junta com espaço como separador
print(frase)
Eu gosto de programar
Outro exemplo:
numeros = ["1", "2", "3", "4", "5"]
texto = "-".join(numeros)
print(texto)
1-2-3-4-5
replace()
replace() substitui todas as ocorrências de uma substring por outra:
texto = "Olá mundo, mundo é grande"
novo = texto.replace("mundo", "Python")
print(novo)
Olá Python, Python é grande
Você pode limitar quantas substituições fazer:
texto = "gato gato gato"
novo = texto.replace("gato", "cachorro", 2) # substitui só as 2 primeiras
print(novo)
cachorro cachorro gato
in — verificar se substring existe
Para saber se uma substring existe em uma string, use o operador in:
texto = "Programação é incrível"
print("Programação" in texto) # True
print("Python" in texto) # False
print("gram" in texto) # True (mesmo que "gram" seja parte de "Programação")
True
False
True
Funciona também para listas:
frutas = ["maçã", "banana", "laranja"]
print("banana" in frutas) # True
print("uva" in frutas) # False
True
False
7. Prática com Turtle e listas
Vamos juntar o que aprendemos sobre listas com o Turtle para criar desenhos mais interessantes!
7.1. Lista de cores: alternando cores
import turtle
t = turtle.Turtle()
t.speed(2)
cores = ["red", "blue", "green", "yellow", "purple"]
for cor in cores:
t.color(cor)
# Desenha um quadrado com a cor atual
for _ in range(4):
t.forward(80)
t.left(90)
# Move para longe do quadrado anterior
t.penup()
t.forward(100)
t.pendown()
t.hideturtle()
turtle.done()
Este programa desenha 5 quadrados, cada um com uma cor diferente da lista.
7.2. Gráfico de barras simples
import turtle
t = turtle.Turtle()
t.speed(3)
valores = [100, 150, 80, 200, 120]
for valor in valores:
t.color("blue")
t.begin_fill()
# Desenha um retângulo onde a altura é proporcional ao valor
t.forward(valor)
t.left(90)
t.forward(40)
t.left(90)
t.forward(valor)
t.left(90)
t.forward(40)
t.left(90)
t.end_fill()
# Move para a próxima barra
t.penup()
t.forward(60)
t.pendown()
t.hideturtle()
turtle.done()
Este programa cria um gráfico de barras onde cada barra tem altura proporcional ao seu valor na lista.
7.3. Desenhar um nome letra por letra
import turtle
t = turtle.Turtle()
t.speed(2)
nome = "PYTHON"
cores = ["red", "blue", "green", "yellow", "purple", "orange"]
for i, letra in enumerate(nome):
cor = cores[i % len(cores)] # alterna entre as cores
t.color(cor)
t.pensize(3)
t.write(letra, font=("Arial", 30, "bold"))
t.penup()
t.forward(40)
t.pendown()
t.hideturtle()
turtle.done()
Repare em cores[i % len(cores)] — isso garante que quando i fica maior que o número de cores, volta ao início e repete!
8. Exercícios
a) Crie uma lista com 5 nomes. Ordene a lista em ordem alfabética e exiba. Depois, exiba em ordem inversa.
b) Crie um programa que peça 5 notas ao usuário e armazene em uma lista. Exiba a maior nota, a menor nota e a média.
Dica: use max(), min() e calcule a soma dividida pelo tamanho.
c) Peça uma frase ao usuário. Conte quantas palavras tem (use split()), converta para maiúsculas e exiba a frase invertida (use slicing com [::-1]).
d) Com o Turtle, crie um gráfico de barras: peça ao usuário 5 valores (de 0 a 200) e armazene em uma lista. Desenhe barras proporcionais aos valores, usando cores diferentes para cada barra. Dica: use uma lista de cores como no exemplo 7.1.
e) Crie um programa que comece com uma lista vazia. Use um while e peça valores ao usuário, adicionando à lista com append(), até o usuário digitar "parar". No final, exiba o total de números adicionados.
f) Peça uma frase ao usuário. Conte quantas vogais tem na frase (a, e, i, o, u). Use um for para iterar sobre cada caractere.
Dica: use letra.lower() e in "aeiou" para verificar.
g) Crie uma lista com números de 1 a 20. Use slicing para exibir: os 5 primeiros, os 5 últimos e todos os números em posições pares (índices 0, 2, 4...).
h) Com o Turtle, peça um nome ao usuário. Desenhe o nome no Turtle, com cada letra em uma posição diferente e cores diferentes. Use enumerate() para controlar a posição e a cor.
Dica: use t.penup(), t.goto() para mudar de posição.
i) Crie um programa que peça uma lista de palavras (até o usuário digitar "fim"). Depois, crie uma sigla com a primeira letra de cada palavra, em maiúsculas. Por exemplo: ["Python", "é", "Legal"] vira "PÉL".
Dica: use palavra[0] para pegar a primeira letra e upper() para maiúsculas.
j) Crie um gerenciador de lista de compras no terminal:
- Comece com uma lista vazia
- Exiba um menu: (a)dicionar, (r)emover, (l)istar, (s)air
- Se escolher 'a', peça um item e adicione à lista
- Se escolher 'r', peça o índice e remova da lista (com tratamento de erro se inválido)
- Se escolher 'l', exiba todos os itens numerados
- Se escolher 's', saia do programa
Use um while para manter o menu rodando.
9. Desafio de capítulo: Analisador de texto
Crie um programa que peça um texto longo ao usuário (pode ser uma frase, um parágrafo, uma música). O programa deve realizar as seguintes análises:
- Contar caracteres: quantos caracteres tem no total (incluindo espaços)?
- Contar palavras: quantas palavras tem? Use
split(). - Encontrar a palavra mais longa: itere sobre a lista de palavras e encontre qual tem mais caracteres.
- Criar uma sigla: pegue a primeira letra de cada palavra (em maiúsculas).
- Texto invertido: exiba o texto inteiro de trás para frente.
- Substituições: peça ao usuário uma palavra e uma substituição, e mostre o texto alterado.
- Estatística de vogais: conte quantas vezes cada vogal (a, e, i, o, u) aparece.
Exemplo de saída:
Digite um texto: "Python é incrível para programação"
===== ANÁLISE DO TEXTO =====
Caracteres: 35
Palavras: 5
Palavra mais longa: "programação" (13 caracteres)
Sigla: PEIPI
Texto invertido: "oãçamargorp arap levírcni é nohtyP"
Estatística de vogais:
a: 4
e: 2
i: 3
o: 2
u: 0
Dicas:
- Use len() para contar caracteres
- Use split() e len(lista) para contar palavras
- Use um for aninhado para encontrar a palavra mais longa
- Use slicing [::-1] para inverter
- Use replace() para substituições
- Para contar vogais, use um for e count() (método de string que conta ocorrências de uma substring)