Listas Avançadas e Tuplas
Na última lição, aprendemos operações básicas de listas. Agora vamos explorar alguns conceitos mais "pytônicos" — a emoção das list comprehensions (uma linha fazendo o trabalho de cinco), e tuplas (a "lista imutável") e quando usá-las. Depois disso, seu código se parecerá cada vez mais com o de um verdadeiro programador Python.
1. Ordenação Avançada de Listas
Na Lição 10, aprendemos o básico de sort() e sorted(). Eles também aceitam um parâmetro key para especificar "qual regra usar para ordenar."
# Ordenar por comprimento da string
words = ["Python", "Java", "JavaScript", "C", "Go"]
sorted_by_len = sorted(words, key=len)
print(sorted_by_len) # ['C', 'Go', 'Java', 'Python', 'JavaScript']
# Ordenar pelo último caractere
words = ["banana", "apple", "cherry", "date"]
sorted_by_last = sorted(words, key=lambda w: w[-1])
print(sorted_by_last) # ['banana', 'date', 'apple', 'cherry']
# Ordenar por um elemento específico em uma tupla
scores = [("João Silva", 85), ("Maria Souza", 92), ("Pedro Santos", 78)]
sorted_scores = sorted(scores, key=lambda s: s[1], reverse=True)
print(sorted_scores) # [('Maria Souza', 92), ('João Silva', 85), ('Pedro Santos', 78)]
key é extremamente útil — você pode passar qualquer função que receba um argumento e retorne um valor. sorted() usará esse valor de retorno para ordenação. O lambda acima é uma função anônima, abordada em detalhes depois.
Exemplo: Gerando um Ranking (Dificuldade ⭐⭐)
# Ranking de jogo — ordenar por pontuação decrescente
players = [
("Jogador 1", 3500),
("Jogador 2", 5200),
("Jogador 3", 2800),
("Jogador 4", 4100),
]
# Ordenar por pontuação decrescente
ranked = sorted(players, key=lambda p: p[1], reverse=True)
print("=== Ranking ===")
for i, (name, score) in enumerate(ranked, 1):
print(f"#{i}: {name} — {score} pontos")
Saída:
=== Ranking ===
#1: Jogador 2 — 5200 pontos
#2: Jogador 4 — 4100 pontos
#3: Jogador 1 — 3500 pontos
#4: Jogador 3 — 2800 pontos
2. List Comprehensions
List comprehensions são um dos recursos mais amados do Python — gerar uma nova lista com uma única linha de código.
Sintaxe Básica
[expressão for variável in iterável]
Tradicional vs. Comprehension
# Gerar quadrados de 0~9 — forma tradicional
squares = []
for i in range(10):
squares.append(i ** 2)
print(squares) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# Usando list comprehension — uma linha
squares = [i ** 2 for i in range(10)]
print(squares) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Comprehension com Condições
# Filtrar números pares
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = [n for n in numbers if n % 2 == 0]
print(evens) # [2, 4, 6, 8, 10]
# Converter strings para maiúsculas
words = ["hello", "world", "python"]
upper_words = [w.upper() for w in words]
print(upper_words) # ['HELLO', 'WORLD', 'PYTHON']
# Filtrar palavras com comprimento >= 5
words = ["cat", "elephant", "dog", "giraffe", "ant"]
long_words = [w for w in words if len(w) >= 5]
print(long_words) # ['elephant', 'giraffe']
Exemplo: Processamento de Dados (Dificuldade ⭐⭐)
# Dados brutos — podem conter valores vazios e espaços extras
raw_data = [" João Silva ", "", " Maria Souza ", " Pedro Santos ", "", " Ana Oliveira "]
# Limpeza em uma etapa com comprehension: strip + filtrar vazios
cleaned = [name.strip() for name in raw_data if name.strip()]
print(cleaned) # ['João Silva', 'Maria Souza', 'Pedro Santos', 'Ana Oliveira']
# Processamento numérico
temps_c = [0, 10, 20, 30, 40]
temps_f = [c * 9 / 5 + 32 for c in temps_c]
print(temps_f) # [32.0, 50.0, 68.0, 86.0, 104.0]
3. O que é uma Tupla
Tuplas são definidas com parênteses (). São similares a listas, mas com uma diferença chave — tuplas são imutáveis; uma vez criadas, não podem ser modificadas.
# Definir tuplas
point = (3, 5)
color = (255, 0, 0)
empty = ()
single = (42,) # Nota: tuplas de um elemento devem ter vírgula!
print(point) # (3, 5)
print(type(point)) # <class 'tuple'>
Tuplas são Imutáveis
point = (3, 5)
# point[0] = 10 ← Erro! Tuplas não podem ser modificadas
print(point[0]) # 3 — pode ler, não pode modificar
Por que Tuplas são Necessárias
A imutabilidade traz dois benefícios:
1. Podem ser usadas como chaves de dicionário (listas não podem, porque são mutáveis)
# Tuplas podem ser chaves de dicionário
locations = {
(35.68, 139.76): "Tóquio",
(31.23, 121.47): "Xangai",
}
print(locations[(35.68, 139.76)]) # Tóquio
# Listas não podem ser chaves
# d = {[1, 2]: "erro"} ← Daria erro!
2. Representa dados que não devem ser modificados
# Coordenadas, cores, configurações — dados "imutáveis" são adequados para tuplas
RGB_RED = (255, 0, 0) # Valor de vermelho não deve ser modificado
DEFAULT_CONFIG = ("localhost", 8080, "admin")
4. Desempacotamento de Tuplas
Um dos recursos mais úteis de tuplas — desempacotamento, atribuindo elementos da tupla diretamente a múltiplas variáveis:
point = (3, 5)
x, y = point # Desempacotamento
print(x) # 3
print(y) # 5
# Troca de variáveis — essencialmente desempacotamento de tupla
a, b = 10, 20
a, b = b, a # Lado direito constrói tupla (20, 10), depois desempacota
print(a, b) # 20 10
# Função retornando múltiplos valores
def get_min_max(numbers):
return min(numbers), max(numbers)
result = get_min_max([3, 1, 4, 1, 5])
print(result) # (1, 5)
low, high = get_min_max([3, 1, 4, 1, 5])
print(f"Min: {low}, Max: {high}") # Min: 1, Max: 5
Usando _ para Ignorar Valores Não Desejados
data = ("João Silva", 25, "São Paulo", "Engenheiro")
name, _, city, _ = data # Use _ para significar "não me importo com isso"
print(f"{name} mora em {city}") # João Silva mora em São Paulo
Exemplo: Cálculo de Coordenadas (Dificuldade ⭐⭐)
# Define dois pontos
p1 = (1, 2)
p2 = (4, 6)
# Desempacota para cálculo de distância
x1, y1 = p1
x2, y2 = p2
distance = ((x2 - x1) 2 + (y2 - y1) 2) ** 0.5
print(f"Distância: {distance:.2f}") # 5.00
# Usando enumerate para iteração indexada
fruits = ["maçã", "banana", "laranja"]
for i, fruit in enumerate(fruits, 1):
print(f"{i}. {fruit}")
Saída:
Distância: 5.00
1. maçã
2. banana
3. laranja
5. Guia de Seleção: Lista vs. Tupla
| Característica | Lista | Tupla |
|---|---|---|
| Mutável | ✅ Pode adicionar/remover/alterar | ❌ Imutável |
| Velocidade | Ligeiramente mais lenta | Ligeiramente mais rápida |
| Memória | Ligeiramente maior | Ligeiramente menor |
| Pode ser chave de dict | ❌ | ✅ |
| Caso de uso | Dados frequentemente modificados | Dados fixos e imutáveis |
| Usos típicos | Carrinho de compras, lista de tarefas, dados dinâmicos | Coordenadas, cores, valores de retorno de função |
Casos de Uso Comuns
- Ordenação de ranking: Use
sorted(key=lambda ...)para ordenar dados complexos por regras personalizadas. - Limpeza de dados: Use list comprehensions para filtrar, transformar e limpar dados em uma linha.
- Coordenadas e geometria: Use tuplas para pontos, retângulos, cores RGB, etc.
- Funções com múltiplos retornos: Funções retornam tuplas
(min, max); chamadores desempacotam diretamente. - Iteração enumerada:
enumerate()retorna tuplas(índice, elemento), desempacotadas diretamente.
❓ Perguntas Frequentes
P: Qual é mais rápido — list comprehensions ou laços for regulares? R: List comprehensions são tipicamente mais rápidas porque executam o laço no nível C em vez do nível Python. No entanto, a diferença é perceptível apenas com grandes quantidades de dados (dezenas de milhares de itens). Na codificação diária, priorize a legibilidade primeiro. P: Por que uma tupla de um elemento precisa de vírgula? Qual a diferença entre
(42)e(42,)? R: Os parênteses em(42)são interpretados como agrupamento matemático, não uma tupla —type((42))retorna<class 'int'>.(42,)é uma tupla. Portanto, tuplas de um elemento devem incluir uma vírgula:(42,). P: Como o parâmetrokeyemsorted()funciona? Dê um exemplo prático. R: O cenário mais comum é ordenar por um atributo específico. Por exemplo, ordenar por comprimento de string:sorted(words, key=len). Ordenar pelo segundo elemento de tuplas em uma lista:sorted(data, key=lambda x: x[1]). Ordenar por valores de dicionário:sorted(dict.items(), key=lambda x: x[1]). O segredo é entender quekeyaceita uma função que mapeia cada elemento a uma chave de ordenação.
📖 Resumo
- O parâmetro
keydesorted()especifica regras de ordenação; combinado comlambdaé muito flexível - List comprehension
[expressão for variável in iterável if condição]cria uma nova lista em uma linha - Tuplas usam sintaxe
(), são imutáveis e podem ser usadas como chaves de dicionário - Tuplas de um elemento devem ter vírgula:
(42,)— senão é um inteiro - Desempacotamento de tupla atribui múltiplos valores a múltiplas variáveis; a troca de variáveis aproveita isso
- Listas para dados mutáveis, tuplas para dados fixos
📝 Atividades
-
Iniciante (Dificuldade ⭐): Use uma list comprehension para gerar os quadrados de todos os números entre 1 e 20 que são divisíveis por 3. Dica:
[expressão for n in range(...) if condição] -
Intermediário (Dificuldade ⭐⭐): Dada uma lista de nomes
names = [" alice ", "BOB", " charlie", " david "], use uma list comprehension em uma etapa: remova espaços + capitalize a primeira letra e minúsculas no resto. Dica:strip()para espaços,title()oucapitalize()para maiúsculas. -
Avançado (Dificuldade ⭐⭐⭐): Escreva uma função
analyze_numbers(*args)que aceita qualquer número de argumentos numéricos e retorna uma tupla(max, min, média, contagem_acima_da_média). Dica: Use*argspara argumentos de comprimento variável; use uma list comprehension para contar valores acima da média.



