Listas são uma das estruturas de dados mais versáteis e amplamente utilizadas em Python. Elas permitem armazenar coleções ordenadas de itens, que podem ser de tipos diferentes, e oferecem diversas operações para manipulação. Nesta aula, você aprenderá a criar listas, acessar seus elementos, fatiar sequências, usar métodos essenciais e entender como a mutabilidade afeta o uso das listas.

Criação e acesso

Uma lista é criada colocando-se elementos separados por vírgulas entre colchetes []. Os elementos podem ser de qualquer tipo: números, strings, outras listas, etc. O acesso a elementos individuais é feito por índices, que começam em 0 para o primeiro elemento. Índices negativos contam a partir do final, com -1 sendo o último elemento.

# Criação de listas
lista_vazia = []
numeros = [1, 2, 3, 4, 5]
mista = [10, "Python", 3.14, ["a", "b"]]

# Acesso por índice
print(numeros[0])   # 1
print(numeros[-1])  # 5
print(mista[1])     # Python
print(mista[3][0])  # a (acesso a sublista)

É importante lembrar que tentar acessar um índice fora do intervalo causa um erro IndexError. Para verificar o comprimento da lista, use a função len().

Fatiamento

O fatiamento (slicing) permite extrair sublistas de uma lista usando a sintaxe lista[inicio:fim:passo]. O índice inicio é incluído, o fim é excluído (ou seja, o intervalo é [inicio, fim)). O parâmetro passo define o incremento entre os elementos (opcional, padrão 1). Se omitidos, os valores padrão são: início = 0, fim = comprimento da lista, passo = 1.

numeros = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

print(numeros[2:5])   # [2, 3, 4]
print(numeros[:4])    # [0, 1, 2, 3]
print(numeros[5:])    # [5, 6, 7, 8, 9]
print(numeros[::2])   # [0, 2, 4, 6, 8]
print(numeros[::-1])  # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] (inverte a lista)

O fatiamento sempre retorna uma nova lista, mesmo que o intervalo seja vazio (ex.: numeros[10:15] retorna []). Isso é útil para criar cópias independentes: copia = lista[:].

Métodos (append, extend, etc.)

Listas em Python possuem diversos métodos embutidos que facilitam a manipulação. Os principais são:

  • append(elemento): adiciona um elemento ao final da lista.
  • extend(iterável): adiciona todos os elementos de um iterável ao final da lista.
  • insert(índice, elemento): insere um elemento em uma posição específica.
  • remove(elemento): remove a primeira ocorrência do elemento (se existir).
  • pop(índice): remove e retorna o elemento na posição; se omitido, remove o último.
  • index(elemento, início, fim): retorna o índice da primeira ocorrência do elemento (pode limitar a busca).
  • count(elemento): conta quantas vezes o elemento aparece.
  • sort(reverse=False, key=...): ordena a lista in-place (modifica a lista original).
  • reverse(): inverte a ordem dos elementos in-place.
  • clear(): remove todos os elementos.
lista = [1, 2, 3]
lista.append(4)        # [1, 2, 3, 4]
lista.extend([5, 6])   # [1, 2, 3, 4, 5, 6]
lista.insert(0, 0)     # [0, 1, 2, 3, 4, 5, 6]
lista.remove(3)        # [0, 1, 2, 4, 5, 6]
ultimo = lista.pop()   # ultimo = 6, lista = [0, 1, 2, 4, 5]
indice = lista.index(4) # 3
contagem = lista.count(2) # 1
lista.sort()           # [0, 1, 2, 4, 5]
lista.reverse()        # [5, 4, 2, 1, 0]
lista.clear()          # []

Métodos como append e extend são eficientes e preferíveis à concatenação com + quando se deseja modificar a lista original. Já sort e reverse atuam in-place e retornam None.

Mutabilidade

Listas são objetos mutáveis, ou seja, seus elementos podem ser alterados após a criação. Isso contrasta com tuplas, que são imutáveis. A mutabilidade permite modificar elementos por atribuição direta, adicionar ou remover itens, e alterar a ordem. No entanto, é preciso cuidado com referências compartilhadas: se duas variáveis apontam para a mesma lista, alterações feitas por uma refletem na outra.

# Mutabilidade: alterando elementos
lista = [1, 2, 3]
lista[0] = 10
print(lista)  # [10, 2, 3]

# Cuidado com referências
lista_a = [1, 2, 3]
lista_b = lista_a
lista_b.append(4)
print(lista_a)  # [1, 2, 3, 4] (ambas apontam para o mesmo objeto)

# Para criar uma cópia independente, use fatiamento ou copy()
lista_c = lista_a[:]
lista_c.append(5)
print(lista_a)  # [1, 2, 3, 4]
print(lista_c)  # [1, 2, 3, 4, 5]

A mutabilidade também afeta operações como += em listas: lista += [4] é equivalente a lista.extend([4]), modificando a lista in-place, ao contrário de lista = lista + [4], que cria uma nova lista.

Boas práticas

Ao trabalhar com listas, prefira métodos como append e extend para adicionar elementos em loops, pois são mais eficientes que concatenações repetidas. Use list comprehensions para criar listas de forma concisa e legível. Evite modificar uma lista enquanto itera sobre ela; se necessário, crie uma cópia.

Referências

Exercícios

  1. Crie uma lista com os números pares de 0 a 20 (inclusive) e imprima o terceiro elemento.
  2. ✓ Resposta:
    pares = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
    print(pares[2])  # 4
  3. Dada a lista [10, 20, 30, 40, 50], use fatiamento para obter e imprimir uma sublista com os elementos 20, 30, 40.
  4. ✓ Resposta:
    numeros = [10, 20, 30, 40, 50]
    sublista = numeros[1:4]
    print(sublista)  # [20, 30, 40]
  5. Adicione os elementos [60, 70] ao final da lista [10, 20, 30] usando um método apropriado e imprima a lista resultante.
  6. ✓ Resposta:
    lista = [10, 20, 30]
    lista.extend([60, 70])
    print(lista)  # [10, 20, 30, 60, 70]
  7. Remova o elemento 30 da lista [10, 20, 30, 40] e imprima a lista e o elemento removido usando pop.
  8. ✓ Resposta:
    lista = [10, 20, 30, 40]
    removido = lista.pop(2)  # índice 2 corresponde ao 30
    print(lista)     # [10, 20, 40]
    print(removido)  # 30
  9. Demonstre que listas são mutáveis: crie uma lista original = [1, 2, 3], atribua-a a outra variável, modifique a segunda e mostre que a original também mudou. Depois, crie uma cópia independente e mostre que a modificação não afeta a original.
  10. ✓ Resposta:
    original = [1, 2, 3]
    ref = original
    ref.append(4)
    print(original)  # [1, 2, 3, 4] (modificada)
    
    copia = original[:]
    copia.append(5)
    print(original)  # [1, 2, 3, 4] (não mudou)
    print(copia)     # [1, 2, 3, 4, 5]