Listas avançado
Esta aula aprofunda o uso de listas em Python, abordando list comprehensions, ordenação com sort e sorted, cópia rasa versus profunda, e aninhamento de listas. O conteúdo inclui exemplos práticos, boas práticas e exercícios com respostas.
Nesta aula, vamos explorar tópicos avançados sobre listas em Python, essenciais para escrever código mais eficiente e expressivo. Você aprenderá a criar listas de forma concisa com list comprehensions, ordenar elementos com sort e sorted, entender as diferenças entre cópia rasa e profunda, e trabalhar com listas aninhadas. Esses conceitos são fundamentais para manipulação de dados e preparação para estruturas mais complexas.
List comprehensions
List comprehensions são uma forma concisa de criar listas aplicando uma expressão a cada item de um iterável, opcionalmente com uma condição de filtro. Elas substituem loops for tradicionais de maneira mais legível e eficiente.
Sintaxe básica: [expressão for item in iterável if condição]. A condição é opcional. Exemplos:
# Quadrados dos números de 0 a 9
quadrados = [x**2 for x in range(10)]
print(quadrados) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# Números pares de 0 a 9
pares = [x for x in range(10) if x % 2 == 0]
print(pares) # [0, 2, 4, 6, 8]
# Converter temperaturas de Celsius para Fahrenheit
celsius = [0, 10, 20, 30, 40]
fahrenheit = [(9/5)*c + 32 for c in celsius]
print(fahrenheit) # [32.0, 50.0, 68.0, 86.0, 104.0]List comprehensions também podem conter múltiplos for e if, simulando aninhamento de loops. Por exemplo, para obter todas as combinações de duas listas:
letras = ['A', 'B']
numeros = [1, 2]
pares = [(l, n) for l in letras for n in numeros]
print(pares) # [('A', 1), ('A', 2), ('B', 1), ('B', 2)]Boas práticas: use list comprehensions para transformações simples; para lógica complexa, prefira loops comuns para manter a legibilidade.
Ordenação (sort, sorted)
Python oferece duas formas principais de ordenar listas: o método sort() (ordena a lista in-place) e a função sorted() (retorna uma nova lista ordenada). Ambos aceitam os parâmetros key e reverse.
Exemplo básico:
numeros = [3, 1, 4, 1, 5, 9]
numeros.sort()
print(numeros) # [1, 1, 3, 4, 5, 9]
# Usando sorted()
letras = ['c', 'a', 'b']
ordenadas = sorted(letras)
print(letras) # ['c', 'a', 'b'] (original inalterado)
print(ordenadas) # ['a', 'b', 'c']O parâmetro key permite especificar uma função que extrai um valor de comparação de cada elemento. Por exemplo, ordenar strings por comprimento:
palavras = ['banana', 'maçã', 'abacaxi', 'uva']
palavras.sort(key=len)
print(palavras) # ['uva', 'maçã', 'banana', 'abacaxi']O parâmetro reverse=True inverte a ordem:
numeros = [3, 1, 4, 1, 5, 9]
numeros.sort(reverse=True)
print(numeros) # [9, 5, 4, 3, 1, 1]Para dicionários, podemos ordenar pelas chaves ou valores:
dados = {'a': 3, 'b': 1, 'c': 2}
ordenado_por_chave = sorted(dados.items())
print(ordenado_por_chave) # [('a', 3), ('b', 1), ('c', 2)]
ordenado_por_valor = sorted(dados.items(), key=lambda item: item[1])
print(ordenado_por_valor) # [('b', 1), ('c', 2), ('a', 3)]Boas práticas: prefira sorted() quando precisar preservar a lista original; use sort() para economizar memória.
Cópia (rasa vs profunda)
Em Python, atribuir uma lista a outra variável não cria uma cópia; ambas referenciam o mesmo objeto. Para evitar alterações indesejadas, é necessário fazer cópias. Existem dois tipos: cópia rasa (shallow copy) e cópia profunda (deep copy).
Cópia rasa cria um novo objeto, mas insere referências aos mesmos objetos contidos na lista original. Ou seja, se a lista contém objetos mutáveis (como outras listas), as alterações nesses objetos internos afetam ambas as listas. Exemplo:
import copy
original = [[1, 2], [3, 4]]
rasa = copy.copy(original)
rasa[0].append(99)
print(original) # [[1, 2, 99], [3, 4]] (modificado)
print(rasa) # [[1, 2, 99], [3, 4]]Cópia profunda cria um novo objeto e recursivamente copia todos os objetos contidos, resultando em uma cópia totalmente independente.
profunda = copy.deepcopy(original)
profunda[0].append(100)
print(original) # [[1, 2, 99], [3, 4]] (inalterado)
print(profunda) # [[1, 2, 99, 100], [3, 4]]Para listas simples (não aninhadas), podemos usar o fatiamento ([:]) ou o método list() para criar uma cópia rasa:
a = [1, 2, 3]
b = a[:] # cópia rasa
b.append(4)
print(a) # [1, 2, 3]
print(b) # [1, 2, 3, 4]Boas práticas: use cópia rasa para listas de objetos imutáveis (números, strings); use cópia profunda quando houver objetos mutáveis aninhados.
Aninhamento
Listas podem conter outras listas, criando estruturas bidimensionais (matrizes) ou de mais dimensões. O acesso aos elementos é feito por índices aninhados.
Exemplo de matriz 3x3:
matriz = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
# Acessar elemento da segunda linha, terceira coluna (índices 1 e 2)
print(matriz[1][2]) # 6Para percorrer todos os elementos, usamos loops aninhados:
for linha in matriz:
for elemento in linha:
print(elemento, end=' ')
print() # quebra de linha
# Saída:
# 1 2 3
# 4 5 6
# 7 8 9List comprehensions também funcionam com listas aninhadas. Por exemplo, para achatar uma matriz:
matriz = [[1, 2], [3, 4], [5, 6]]
plana = [num for linha in matriz for num in linha]
print(plana) # [1, 2, 3, 4, 5, 6]Boas práticas: cuidado com cópias de listas aninhadas; use compreensão de listas para operações concisas.
Boas práticas e observações finais
Ao trabalhar com listas em Python, lembre-se de que a legibilidade é importante. Prefira list comprehensions para operações simples, mas não exagere: expressões muito longas podem ser difíceis de entender. Sempre considere o uso de cópias para evitar efeitos colaterais. Em ordenações, explore o parâmetro key para personalizar critérios. Pratique com listas aninhadas para se familiarizar com índices e loops.
Exercícios
Crie uma lista com os quadrados dos números ímpares de 1 a 20 usando list comprehension.
✓ Resposta:quadrados_impares = [x**2 for x in range(1, 21) if x % 2 != 0] print(quadrados_impares) # [1, 9, 25, 49, 81, 121, 169, 225, 289, 361]Dada a lista
pontos = [(1, 2), (3, 1), (5, 4)], ordene-a pelo segundo elemento de cada tupla usandosorted.✓ Resposta:pontos = [(1, 2), (3, 1), (5, 4)] pontos_ordenados = sorted(pontos, key=lambda p: p[1]) print(pontos_ordenados) # [(3, 1), (1, 2), (5, 4)]Explique a diferença entre cópia rasa e profunda e dê um exemplo onde a cópia rasa não é suficiente.
✓ Resposta:Cópia rasa cria um novo objeto, mas os elementos internos são referências aos mesmos objetos. Cópia profunda cria um novo objeto e recursivamente copia todos os objetos aninhados. Exemplo onde cópia rasa falha:
import copy original = [[1, 2], [3, 4]] rasa = copy.copy(original) rasa[0].append(99) # altera também original print(original) # [[1, 2, 99], [3, 4]]Com deep copy, isso não acontece.
Crie uma matriz 4x4 onde cada elemento é o produto do índice da linha pelo índice da coluna (começando em 0). Use list comprehension aninhada.
✓ Resposta:matriz = [[i * j for j in range(4)] for i in range(4)] for linha in matriz: print(linha) # Saída: # [0, 0, 0, 0] # [0, 1, 2, 3] # [0, 2, 4, 6] # [0, 3, 6, 9]Dada a lista
lista = [3, 1, 2], usesort()para ordená-la em ordem decrescente e depois usesorted()para obter uma nova lista em ordem crescente, mantendo a original inalterada. Mostre o resultado.✓ Resposta:lista = [3, 1, 2] lista.sort(reverse=True) print(lista) # [3, 2, 1] nova_lista = sorted(lista) # sorted() não modifica a original print(lista) # [3, 2, 1] (inalterada) print(nova_lista) # [1, 2, 3]