Python Removendo Itens
No mercado, a Ana vai pondo os produtos no carrinho e riscando cada um da lista. Na cantina da escola, quem é atendido sai da fila. No fim do mês, a lista inteira vai para o lixo. Tirar itens de uma lista é tão comum quanto pôr, e o Python tem quatro jeitos de fazer isso, cada um para uma situação: remove(), pop(), del e clear().
- A tirar um item pelo valor com
remove(), e o que acontece com itens repetidos. - A tirar um item pelo índice com
pop(), e a usar o item que ele devolve. - A apagar itens e fatias com
del, e a esvaziar a lista comclear(). - A tirar todas as ocorrências de um item.
- Por que remover itens dentro de um
forpula itens, e como fazer certo. - Os erros reais: o
ValueErrordoremovee oIndexErrordopop.
A ideia: riscar pelo nome ou pela posição
Há duas maneiras de dizer a alguém qual item riscar da lista:
- Pelo nome: "risca o café". Você não sabe (nem precisa saber) em que posição ele está. É o
remove("café"). - Pela posição: "risca o primeiro", "risca o último". Você não liga para qual é o item. É o
pop(0), opop()e odel lista[0].
Em qualquer dos casos, os itens que vêm depois andam uma casa para a esquerda para ocupar o lugar vazio. A lista nunca fica com um "buraco".
1. remove(): tirar pelo valor
compras = ["arroz", "feijão", "café", "leite"]
compras.remove("café")
print(compras)
cesta = ["pão", "leite", "pão", "ovos", "pão"]
cesta.remove("pão")
print(cesta)
$ python3 remove.py ['arroz', 'feijão', 'leite'] ['leite', 'pão', 'ovos', 'pão']
- compras.remove("café")
- "Lista de compras, remova o café". O Python procura o primeiro item igual a
"café"e o tira. O leite, que estava no índice 3, passa para o 2. - cesta.remove("pão")
- Com itens repetidos, o
removetira só o primeiro que encontrar. Sobraram dois pães.
Como o append (aula Adicionando Itens), o remove muda a própria lista e devolve None. Por isso a linha é só compras.remove("café"), sem =.
Tirando sem dar erro, e tirando todos
Se o item não estiver na lista, o remove para o programa com um erro (você vai vê-lo em Quando dá errado). O jeito seguro é perguntar antes com in. E, para tirar todas as ocorrências, repita enquanto o item ainda estiver lá:
compras = ["arroz", "feijão", "café", "leite"]
item = "açúcar"
if item in compras:
compras.remove(item)
print(f"{item} riscado.")
else:
print(f"{item} não estava na lista.")
cesta = ["pão", "leite", "pão", "ovos", "pão"]
while "pão" in cesta:
cesta.remove("pão")
print(cesta)
$ python3 remove_seguro.py açúcar não estava na lista. ['leite', 'ovos']
O while "pão" in cesta: (aula while) remove um pão por volta e para quando não sobra nenhum. Funciona bem em listas pequenas como esta; para listas grandes, o jeito mais rápido é criar uma lista nova só com o que fica, como você vai ver na seção 5.
Missão: a Ana já pôs o sabão no carrinho. Use remove para riscá-lo da lista, antes do print.
compras = ["arroz", "feijão", "sabão", "leite"] print(compras)
compras = ["arroz", "feijão", "sabão", "leite"]
compras.remove("sabão")
print(compras)
2. pop(): tirar pela posição (e ficar com o item)
O pop ("estourar", "tirar de uma vez") tem duas diferenças em relação ao remove: ele recebe o índice, e não o valor; e ele devolve o item que tirou, para você usar. Sem índice, ele tira o último.
>>> compras = ["arroz", "feijão", "café", "leite"] >>> compras.pop() 'leite' >>> compras ['arroz', 'feijão', 'café'] >>> compras.pop(1) 'feijão' >>> compras ['arroz', 'café']
No modo interativo, o 'leite' que aparece logo depois de compras.pop() é o valor devolvido: o item que saiu. Depois, pop(1) tirou o item de índice 1, o feijão.
A fila da cantina
Uma fila é o exemplo perfeito: quem chegou primeiro é atendido primeiro (sai do começo, pop(0)), e o programa precisa saber quem está sendo atendido. É para isso que serve o valor devolvido:
fila = ["Ana", "Bruno", "Carla", "Davi"]
ultimo = fila.pop()
print(f"{ultimo} desistiu e saiu da fila.")
atendido = fila.pop(0)
print(f"Atendendo: {atendido}")
print(f"Ainda na fila: {fila}")
$ python3 fila.py Davi desistiu e saiu da fila. Atendendo: Ana Ainda na fila: ['Bruno', 'Carla']
- ultimo = fila.pop()
- Tira o último (o Davi) e guarda o nome dele em
ultimo. Aqui o=está certo: opop, ao contrário doappende doremove, devolve algo útil. - atendido = fila.pop(0)
- Tira o primeiro (a Ana). O Bruno passa a ser o índice 0.
Missão: a cantina vai atender duas pessoas, sempre a primeira da fila. Complete as duas linhas com fila.pop(0) no lugar dos "".
fila = ["Ana", "Bruno", "Carla"]
atendido = ""
print(f"Atendendo: {atendido}")
atendido = ""
print(f"Atendendo: {atendido}")
print(f"Ainda na fila: {fila}")
fila = ["Ana", "Bruno", "Carla"]
atendido = fila.pop(0)
print(f"Atendendo: {atendido}")
atendido = fila.pop(0)
print(f"Atendendo: {atendido}")
print(f"Ainda na fila: {fila}")
3. del: apagar pelo índice ou uma fatia
del (de delete, "apagar") não é um método: é uma palavra-chave do Python, escrita antes do que você quer apagar, sem ponto e sem parênteses. Ela apaga um item pelo índice, como o pop, mas não devolve nada. E apaga fatias inteiras:
compras = ["arroz", "feijão", "café", "leite", "sabão", "sal"] del compras[0] print(compras) del compras[1:3] print(compras) del compras[-1] print(compras) compras.clear() print(compras)
$ python3 del.py ['feijão', 'café', 'leite', 'sabão', 'sal'] ['feijão', 'sabão', 'sal'] ['feijão', 'sabão'] []
- del compras[0]
- Apaga o item de índice 0, o arroz.
- del compras[1:3]
- Apaga a fatia dos índices 1 e 2 (café e leite), como você viu fatias em Acessando Itens.
- del compras[-1]
- Apaga o último, o sal.
- compras.clear()
- O método
clear("limpar") tira todos os itens. A lista continua existindo, só que vazia:[].
del sem índice apaga a variável
Cuidado com a diferença entre esvaziar a lista e apagar a variável:
>>> compras = ["arroz", "café"]
>>> del compras
>>> compras
Traceback (most recent call last):
File "<python-input-2>", line 1, in <module>
compras
NameError: name 'compras' is not defined
del compras, sem colchetes, apaga o nome compras: depois disso, é como se a variável nunca tivesse existido (NameError). Para ter uma lista vazia e continuar usando, é compras.clear().
4. Qual usar?
| Você sabe… | …e quer | Use | Se não existir |
|---|---|---|---|
| O valor ("o café") | Tirar a primeira ocorrência | lista.remove("café") | ValueError |
| O valor | Tirar todas as ocorrências | while x in lista: lista.remove(x) ou uma lista nova (seção 5) | Não faz nada |
| A posição | Tirar e usar o item | item = lista.pop(i) | IndexError |
| Nada (quer o último) | Tirar e usar o último | item = lista.pop() | IndexError se a lista estiver vazia |
| A posição | Só apagar | del lista[i] | IndexError |
| Um trecho | Apagar vários seguidos | del lista[a:b] | Não dá erro |
| — | Esvaziar tudo | lista.clear() | — |
5. Removendo dentro de um for: o item pulado
A professora quer tirar da lista todas as notas abaixo de 6. Parece simples: passar pelas notas e remover as baixas.
notas = [4.0, 5.5, 8.0, 3.0, 9.0, 7.5]
for nota in notas:
if nota < 6:
notas.remove(nota)
print(notas)
$ python3 notas_errado.py [5.5, 8.0, 9.0, 7.5]
O 5.5 escapou, e nenhum erro apareceu. O que aconteceu? O for anda pela lista pelo índice: primeiro o 0, depois o 1, o 2…
- Volta 1, índice 0: a nota é 4.0. É menor que 6, então sai. A lista vira
[5.5, 8.0, 3.0, 9.0, 7.5]: todo mundo andou uma casa para a esquerda, e o 5.5 agora está no índice 0. - Volta 2, índice 1: o
forsegue em frente, para o índice 1, onde agora está o 8.0. O 5.5, que foi para o índice 0, nunca é olhado. - Volta 3, índice 2: o 3.0. Sai. O 9.0 e o 7.5 andam para a esquerda.
- Volta 4, índice 3: o 7.5 (o 9.0 foi para o índice 2 e também foi pulado, mas ele não precisava sair).
É como riscar a lista de compras enquanto uma pessoa a reescreve sem os itens riscados: você perde o lugar. Dois jeitos certos:
notas = [4.0, 5.5, 8.0, 3.0, 9.0, 7.5]
for nota in notas[:]:
if nota < 6:
notas.remove(nota)
print(notas)
$ python3 notas_certo.py [8.0, 9.0, 7.5]
O notas[:] é uma cópia da lista (uma fatia do começo ao fim, aula Copiando Listas). O for anda pela cópia, que não muda, e o remove tira os itens da original. Ninguém perde o lugar.
notas = [4.0, 5.5, 8.0, 3.0, 9.0, 7.5]
aprovadas = []
for nota in notas:
if nota >= 6:
aprovadas.append(nota)
print(aprovadas)
$ python3 notas_certo2.py [8.0, 9.0, 7.5]
O segundo jeito pensa ao contrário: em vez de tirar as notas baixas, ele monta uma lista nova só com as que ficam. A lista original não muda durante o for, então nada é pulado. Este é o jeito mais usado (e o mais rápido em listas grandes), e na aula List Comprehension você vai escrevê-lo numa linha só.
Nunca tire (nem ponha) itens numa lista enquanto um for anda por essa mesma lista. Ande por uma cópia (for x in lista[:]) ou monte uma lista nova.
Quando dá errado
compras = ["arroz", "feijão", "café", "leite"]
compras.remove("açúcar")
print(compras)
$ python3 remove_erro.py
Traceback (most recent call last):
File "/home/ana/remove_erro.py", line 2, in <module>
compras.remove("açúcar")
~~~~~~~~~~~~~~^^^^^^^^^^
ValueError: list.remove(x): x not in list
Linha por linha:
File "/home/ana/remove_erro.py", line 2: o erro foi na linha 2. Oprintda linha 3 não chegou a rodar.- Os
^^^^marcam o("açúcar"): o valor pedido é o problema. ValueError: list.remove(x): x not in list: "erro de valor:list.remove(x): x não está na lista". Oxquer dizer "o valor que você pediu"; a mensagem não repete qual era. É a mesma mensagem doindex(), que você viu em Acessando Itens.
Lembre que a comparação é exata: remove("Café") ou remove("cafe") numa lista com "café" dão o mesmo erro. Como consertar: confira antes com if item in lista:, como no remove_seguro.py.
remove
A Ana queria tirar o primeiro item e escreveu remove(0):
>>> compras = ["arroz", "café"]
>>> compras.remove(0)
Traceback (most recent call last):
File "<python-input-1>", line 1, in <module>
compras.remove(0)
~~~~~~~~~~~~~~^^^
ValueError: list.remove(x): x not in list
O remove não sabe nada de índices: ele procurou na lista um item igual ao número 0, e não havia nenhum. (Pior: numa lista de números, como [0, 5, 7], o remove(0) funcionaria, mas tiraria o valor 0, onde quer que ele estivesse.) Como consertar: pelo índice, use pop(0) ou del lista[0].
pop numa lista vazia ou num índice que não existe
fila = ["Ana"] print(fila.pop(0)) print(fila.pop(0))
$ python3 fila_vazia.py
Ana
Traceback (most recent call last):
File "/home/ana/fila_vazia.py", line 3, in <module>
print(fila.pop(0))
~~~~~~~~^^^
IndexError: pop from empty list
O primeiro pop atendeu a Ana, e a fila ficou vazia. O segundo não tinha de onde tirar: pop from empty list, "pop de uma lista vazia". Com uma lista que tem itens, mas um índice grande demais, a mensagem muda um pouco:
>>> compras = ["arroz", "café"]
>>> compras.pop(10)
Traceback (most recent call last):
File "<python-input-1>", line 1, in <module>
compras.pop(10)
~~~~~~~~~~~^^^^
IndexError: pop index out of range
Como consertar: antes de tirar, confira se ainda tem alguém: if fila: (uma lista vazia conta como falso, aula Booleanos) ou if len(fila) > 0:. Um laço que atende até a fila acabar fica assim: while fila: atendido = fila.pop(0).
remove
>>> compras = ["arroz", "café"]
>>> item = compras.remove("arroz")
>>> print(item)
None
A Ana queria guardar o item que saiu, mas o remove devolve None (você já sabe qual é o item: foi você que o escreveu!). Só o pop devolve o item removido. E nunca escreva compras = compras.remove(…): a lista vira None, como o append da aula Adicionando Itens.
for
Você viu na seção 5: sem erro nenhum, o resultado sai errado. Se uma remoção "esqueceu" alguns itens, procure um remove, pop ou del dentro de um for que anda pela mesma lista.
Referência rápida
| Escrita | O que faz | Devolve |
|---|---|---|
lista.remove(x) | Tira a primeira ocorrência do valor x | None |
lista.pop() | Tira o último item | O item tirado |
lista.pop(i) | Tira o item de índice i | O item tirado |
del lista[i] | Apaga o item de índice i | — (é uma instrução) |
del lista[a:b] | Apaga a fatia | — |
lista.clear() | Tira todos os itens; a lista fica [] | None |
del lista | Apaga a variável | — |
| Sintoma | Causa provável |
|---|---|
ValueError: list.remove(x): x not in list | O valor não está na lista (maiúsculas, acentos?) ou passou um índice para o remove |
IndexError: pop from empty list | pop numa lista vazia: confira com if lista: |
IndexError: pop index out of range | pop(i) com um índice que não existe |
NameError: name 'compras' is not defined depois de um del | del compras apagou a variável; para esvaziar, clear() |
| Sobrou um item que deveria ter saído | Remoção dentro de um for na mesma lista, ou remove tirou só a primeira ocorrência |
A variável vale None | Guardou o resultado do remove ou do clear |
Exercícios
1. Riscando pelo nome
Complete para tirar o leite da lista:
2. O último a sair
Complete para tirar o último item e guardá-lo em item:
3. Quanto sobrou?
Com cesta = ["pão", "pão", "ovos", "pão"], depois de cesta.remove("pão"), quantos pães ficam na cesta?
4. Qual destes tira o primeiro item e devolve o item tirado?
5. Depois de compras.clear(), o que print(compras) mostra?
6. Por que remover itens de uma lista dentro de um for que anda por ela mesma é perigoso?
Missão final: só as notas de aprovação
Missão: o programa deveria tirar todas as notas abaixo de 6, mas o 5.5 escapa. Conserte o laço (dica: faça o for andar por uma cópia, notas[:], ou monte uma lista nova só com as notas que ficam).
notas = [4.0, 5.5, 8.0, 3.0, 9.0, 7.5]
for nota in notas:
if nota < 6:
notas.remove(nota)
print(notas)
notas = [4.0, 5.5, 8.0, 3.0, 9.0, 7.5]
for nota in notas[:]:
if nota < 6:
notas.remove(nota)
print(notas)
Resumo
remove(x)tira pelo valor, só a primeira ocorrência; se não houver,ValueError. Pergunte antes comin.pop(i)tira pelo índice e devolve o item;pop()tira o último. Lista vazia:IndexError.del lista[i]edel lista[a:b]apagam pelo índice ou pela fatia;del listaapaga a variável.clear()esvazia a lista, que continua existindo.- Os itens seguintes sempre andam para a esquerda: não fica buraco.
- Para tirar todas as ocorrências:
while x in lista: lista.remove(x), ou uma lista nova só com o que fica. - Nunca remova itens dentro de um
forque anda pela mesma lista: ande por uma cópia (lista[:]) ou monte uma lista nova.