Python Adicionando Itens
A lista de compras nunca fica pronta de uma vez. A Ana abre o armário, vê que o café acabou e escreve "café" no fim da folha; a vizinha pede para ela trazer sal e óleo, e mais dois itens entram. Na aula Alterando Itens, você viu que compras[4] = "sabão" dá erro numa lista de 4 itens: a atribuição só troca o que já existe. Para acrescentar itens, a lista tem métodos próprios. É o assunto desta aula.
- A pôr um item no fim com
append(). - A montar uma lista do zero, começando de
[], inclusive com o que a pessoa digita. - A pôr um item numa posição escolhida com
insert(). - A juntar uma lista inteira à outra com
extend(),+e+=, e a diferença entre elas. - Os erros reais: o
appendque devolveNone(lista = lista.append(x)), oAttributeErrordeNoneType, o texto que vira letras soltas e o+com um texto.
A ideia: escrever no fim da folha
Quando a Ana lembra de um item novo, o jeito mais natural é escrevê-lo no fim da lista, embaixo do último. Às vezes, porém, ela quer encaixar um item no meio ("o pão tem de ser o primeiro, para eu não esquecer"). E às vezes recebe uma listinha inteira de outra pessoa para juntar à dela. São três situações, e cada uma tem o seu método:
| Situação | Método | Tradução |
|---|---|---|
| Um item no fim | append(item) | "anexar", "acrescentar no fim" |
| Um item numa posição | insert(posição, item) | "inserir" |
| Vários itens (outra lista) no fim | extend(outra_lista) | "estender" |
Os três alteram a própria lista (ela é mutável, como você viu em Alterando Itens). Guarde essa frase: ela é a chave do erro mais famoso desta aula.
1. append(): um item no fim
compras = ["arroz", "feijão"]
print(compras)
compras.append("café")
print(compras)
compras.append("leite")
print(compras)
print(f"Agora são {len(compras)} itens.")
- compras
- A lista que vai receber o item.
- .
- O ponto: "da lista
compras, use o método…". Métodos são funções que pertencem a um valor. - append
- O método que acrescenta um item no fim.
- ("café")
- Entre parênteses, o item novo. Exatamente um.
$ python3 append.py ['arroz', 'feijão'] ['arroz', 'feijão', 'café'] ['arroz', 'feijão', 'café', 'leite'] Agora são 4 itens.
A cada append, a lista ganhou um item no fim e o len aumentou 1. Repare que a linha compras.append("café") não tem =: ela não cria uma lista nova para guardar em algum lugar. Ela muda a lista compras que já existe.
Missão: use append duas vezes para acrescentar "leite" e depois "pão" à lista, antes do print.
compras = ["arroz", "feijão"] print(compras)
compras = ["arroz", "feijão"]
compras.append("leite")
compras.append("pão")
print(compras)
2. Montando uma lista do zero
O uso mais comum do append é encher uma lista vazia, um item de cada vez. A Ana quer que o programa pergunte os itens e monte a lista para ela:
compras = []
for i in range(3):
item = input("Item: ")
compras.append(item)
print(compras)
$ python3 montar.py Item: ovos Item: pão Item: leite ['ovos', 'pão', 'leite']
compras = []: a lista começa vazia. Ela precisa existir antes do laço, senão não há onde fazer oappend.- O
for i in range(3)(aula range()) repete o bloco 3 vezes. - A cada volta, o
input()lê um item e oappendo põe no fim. - Depois do laço, a lista tem os 3 itens, na ordem em que foram digitados.
E se a Ana não souber quantos itens vão ser? Um while com uma palavra para parar (aulas while e break e continue):
compras = []
while True:
item = input("Item (ou fim): ")
if item == "fim":
break
compras.append(item)
print(f"Sua lista tem {len(compras)} itens: {compras}")
$ python3 montar2.py Item (ou fim): café Item (ou fim): leite Item (ou fim): fim Sua lista tem 2 itens: ['café', 'leite'] $ python3 montar2.py Item (ou fim): fim Sua lista tem 0 itens: []
Na segunda vez, a Ana digitou fim logo de cara, e a lista ficou vazia, sem erro nenhum. Repare que o "fim" não entrou na lista: o break vem antes do append.
3. insert(): um item numa posição
Na fila da cantina, a Ana chegou primeiro e precisa entrar no começo; depois o Beto vai entrar no meio. O insert recebe dois valores: primeiro o índice onde o item vai ficar, depois o item.
fila = ["Bruno", "Carla", "Davi"] fila.insert(0, "Ana") print(fila) fila.insert(2, "Beto") print(fila) fila.insert(100, "Zeca") print(fila)
$ python3 insert.py ['Ana', 'Bruno', 'Carla', 'Davi'] ['Ana', 'Bruno', 'Beto', 'Carla', 'Davi'] ['Ana', 'Bruno', 'Beto', 'Carla', 'Davi', 'Zeca']
- fila.insert(0, "Ana")
- Põe a Ana no índice 0, o começo. Todos os outros andam uma casa para a direita: o Bruno, que era o 0, passa a ser o 1.
- fila.insert(2, "Beto")
- O Beto fica no índice 2, ou seja, antes de quem estava no 2 (a Carla).
- fila.insert(100, "Zeca")
- Um índice maior que a lista não dá erro: o item simplesmente vai para o fim, como num
append.
Com um índice negativo, cuidado: insert(-1, item) não põe no fim. Ele põe antes do último, porque o item novo ocupa o índice -1 e empurra quem estava lá:
>>> compras = ["arroz", "feijão"]
>>> compras.append("café")
>>> print(compras.append("leite"))
None
>>> compras
['arroz', 'feijão', 'café', 'leite']
>>> compras.insert(-1, "sal")
>>> compras
['arroz', 'feijão', 'café', 'sal', 'leite']
O sal ficou entre o café e o leite. Para pôr no fim, use append. (E repare na terceira linha: print(compras.append("leite")) mostrou None, mas o leite entrou na lista. Guarde isso para o Quando dá errado.)
insert(0, …) dá mais trabalho ao computador
Para pôr um item no começo, o Python precisa empurrar todos os outros uma casa para a direita. Numa lista de compras, isso não faz diferença nenhuma. Numa lista de um milhão de itens, fazer isso muitas vezes começa a pesar; o append, no fim, é sempre rápido. Quando precisar pôr e tirar coisas do começo o tempo todo, existe uma estrutura feita para isso, o deque (aula O Módulo collections).
4. Juntando listas: extend(), + e +=
A vizinha mandou a listinha dela: sal e óleo. A Ana quer juntar os itens dela à lista de compras.
compras = ["arroz", "feijão"] da_vizinha = ["sal", "óleo"] compras.extend(da_vizinha) print(compras) print(da_vizinha)
$ python3 extend.py ['arroz', 'feijão', 'sal', 'óleo'] ['sal', 'óleo']
O extend acrescentou, no fim de compras, cada um dos itens de da_vizinha. A lista da vizinha ficou como estava.
append de uma lista: a lista dentro da lista
E se a Ana usar append com a lista da vizinha?
compras = ["arroz", "feijão"] compras.append(["sal", "óleo"]) print(compras) print(len(compras))
$ python3 append_lista.py ['arroz', 'feijão', ['sal', 'óleo']] 3
Repare nos colchetes de dentro: o append põe um item no fim, e esse item foi a lista inteira da vizinha. A lista ficou com 3 itens, e o terceiro é uma lista (você viu listas dentro de listas em Acessando Itens). Às vezes é isso mesmo que você quer; quase sempre, quem escreve isso queria o extend.
Com compras = ["arroz", "feijão"] | Resultado | Itens |
|---|---|---|
compras.append(["sal", "óleo"]) | ['arroz', 'feijão', ['sal', 'óleo']] | 3 |
compras.extend(["sal", "óleo"]) | ['arroz', 'feijão', 'sal', 'óleo'] | 4 |
O + e o +=
Como nos textos (aula Juntar e Repetir Textos), o + junta duas listas. Mas há uma diferença importante: o + cria uma lista nova e deixa as duas originais em paz. Já o += muda a lista da esquerda, como o extend.
>>> compras = ["arroz", "feijão"] >>> nova = compras + ["sal", "óleo"] >>> nova ['arroz', 'feijão', 'sal', 'óleo'] >>> compras ['arroz', 'feijão'] >>> compras += ["pão"] >>> compras ['arroz', 'feijão', 'pão']
nova = compras + ["sal", "óleo"]: a listanovatem os 4 itens;comprascontinua com 2. O+não mexeu em ninguém.compras += ["pão"]: agora simcomprasmudou. O+=em listas funciona como oextend. Do lado direito, uma lista (por isso["pão"], com colchetes).
Repetindo: *
Outro operador que vem dos textos: [0] * 3 é uma lista com o 0 repetido 3 vezes. É um jeito rápido de criar o placar de um jogo com três jogadores, todos começando do zero:
>>> placar = [0] * 3 >>> placar [0, 0, 0]
Formas diferentes de adicionar
| Você quer | Escreva | Muda a lista? |
|---|---|---|
| Um item no fim | lista.append(item) | Sim. É o jeito mais usado |
| Um item numa posição | lista.insert(i, item) | Sim. Os outros andam para a direita |
| Os itens de outra lista, no fim | lista.extend(outra) | Sim |
| O mesmo, mais curto | lista += outra | Sim. Igual ao extend |
| Uma lista nova com as duas juntas | nova = lista + outra | Não: as duas continuam como estavam |
| Um item no fim, criando uma lista nova | nova = lista + [item] | Não |
| Uma lista com um valor repetido | [0] * n | Cria uma lista nova |
Quando dá errado
lista = lista.append(x): a lista vira None
Este é, de longe, o erro mais comum com listas. A Ana se acostumou a escrever nome = nome.upper() com textos e fez o mesmo com o append:
compras = ["arroz", "feijão"]
compras = compras.append("café")
print(compras)
compras.append("leite")
$ python3 none.py
None
Traceback (most recent call last):
File "/home/ana/none.py", line 4, in <module>
compras.append("leite")
^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'append'
Vamos por partes:
- Linha 2: o
appendacrescentou o café na lista e devolveuNone, o valor que quer dizer "nada" (aula O Valor None). Métodos que alteram a lista não devolvem a lista: eles fazem o trabalho e devolvemNone. Você viu isso lá em cima, noprint(compras.append("leite")). Ocompras = …guardou esseNonena variável, e a lista (que tinha arroz, feijão e café) ficou sem nome nenhum, perdida. - Linha 3: o
printmostrouNone. Nenhum erro ainda, mas a lista já se foi. - Linha 4:
comprasagora valeNone, eNonenão tem o métodoappend. A mensagemAttributeError: 'NoneType' object has no attribute 'append'quer dizer "erro de atributo: um objeto do tipoNoneType(o tipo doNone) não tem o atributoappend". Os^^^^marcamcompras.append.
Repare que o erro aparece numa linha depois da linha culpada. Quando você vir 'NoneType' object has no attribute …, a pergunta é: "onde essa variável recebeu None?". Quase sempre, foi um x = x.append(…), x = x.sort() ou parecido.
Como consertar: chame o método sozinho, sem =: compras.append("café").
Textos são imutáveis: nome.upper() não pode mudar o texto que está em nome, então ele devolve um texto novo, e você precisa guardá-lo (nome = nome.upper()). Listas são mutáveis: compras.append(x) muda a própria lista e não tem nada novo para devolver. Regra prática: método de lista que altera (append, insert, extend, sort, reverse, remove, clear) devolve None; nunca guarde o resultado deles na própria lista.
No laço, o erro aparece na segunda volta, o que deixa tudo mais confuso:
compras = []
for i in range(3):
item = input("Item: ")
compras = compras.append(item)
print(compras)
$ python3 none2.py
Item: ovos
Item: pão
Traceback (most recent call last):
File "/home/ana/none2.py", line 4, in <module>
compras = compras.append(item)
^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'append'
Na primeira volta, o append funcionou (a lista vazia recebeu os ovos) e devolveu None, que foi guardado em compras. Na segunda volta, compras já era None, e o append do pão quebrou. Você vai consertar isso na missão final.
extend ou no +=: letras soltas
>>> compras.extend("óleo")
>>> compras
['arroz', 'feijão', 'café', 'sal', 'leite', 'ó', 'l', 'e', 'o']
Nenhum erro, e o óleo virou quatro itens: 'ó', 'l', 'e', 'o'. O extend acrescenta cada item do que recebe, e os itens de um texto são as letras. O += faz o mesmo:
>>> compras = ["arroz", "feijão", "pão"] >>> compras += "sal" >>> compras ['arroz', 'feijão', 'pão', 's', 'a', 'l']
Como consertar: para um item, append("óleo"). Para usar extend ou +=, ponha o texto dentro de uma lista: compras += ["sal"].
+ com um texto
Curiosamente, o + (sem o =) não aceita o texto e avisa:
>>> compras = ["arroz", "feijão", "pão"]
>>> compras + "sal"
Traceback (most recent call last):
File "<python-input-1>", line 1, in <module>
compras + "sal"
~~~~~~~~^~~~~~~
TypeError: can only concatenate list (not "str") to list
"Erro de tipo: só dá para concatenar (juntar) uma lista a outra lista, e não um str". O ^ embaixo do + mostra a operação que falhou, e os ~ os dois lados dela. Como consertar: compras + ["sal"].
append só, ou um método que não existe
>>> compras.append("ovos", "farinha")
Traceback (most recent call last):
File "<python-input-2>", line 1, in <module>
compras.append("ovos", "farinha")
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^
TypeError: list.append() takes exactly one argument (2 given)
>>> compras.push("ovos")
Traceback (most recent call last):
File "<python-input-3>", line 1, in <module>
compras.push("ovos")
^^^^^^^^^^^^
AttributeError: 'list' object has no attribute 'push'
list.append() takes exactly one argument (2 given): "oappendrecebe exatamente um argumento (foram dados 2)". Para dois itens, doisappend, oucompras.extend(["ovos", "farinha"]).'list' object has no attribute 'push': em outras linguagens (como o JavaScript), acrescentar no fim se chamapush. No Python, éappend. O mesmo vale paraadd, que é dos conjuntos (aula Conjuntos), não das listas.
Referência rápida
| Escrita | O que faz | Devolve |
|---|---|---|
lista.append(x) | Põe x no fim | None |
lista.insert(i, x) | Põe x no índice i; quem estava lá anda para a direita. Índice grande demais = no fim | None |
lista.extend(outra) | Põe cada item de outra no fim (um texto vira letras) | None |
lista += outra | O mesmo que extend | — |
lista + outra | Cria uma lista nova com as duas; não muda nenhuma | A lista nova |
[x] * n | Uma lista nova com x repetido n vezes | A lista nova |
| Sintoma | Causa provável |
|---|---|
A lista virou None | lista = lista.append(x) (ou insert, extend…): chame sem = |
AttributeError: 'NoneType' object has no attribute 'append' | A variável recebeu None numa linha anterior, quase sempre pelo motivo acima |
| Letras soltas como itens | Texto no extend ou no +=; use append ou ponha o texto numa lista |
| Uma lista dentro da lista | append de uma lista; para juntar os itens, extend |
TypeError: can only concatenate list (not "str") to list | lista + "texto"; use lista + ["texto"] |
TypeError: list.append() takes exactly one argument (2 given) | Dois itens num append |
AttributeError: 'list' object has no attribute 'push' (ou 'add') | O nome certo é append |
| O item entrou antes do último | insert(-1, x); para o fim, append(x) |
Exercícios
1. No fim da lista
Complete o método que põe o açúcar no fim da lista:
2. Primeiro da fila
Complete para pôr a Eva no começo da fila:
3. Quantos itens?
Com a = [1, 2], depois de a.append([3, 4]), quanto vale len(a)?
4. Depois de compras = ["arroz"] e compras = compras.append("feijão"), quanto vale compras?
5. Qual destas linhas deixa a = [1, 2] como [1, 2] e cria uma lista nova [1, 2, 3]?
6. O que letras = ["a"] seguido de letras.extend("bc") deixa em letras?
Missão final: a lista pelo teclado
Missão: o programa deveria perguntar 3 itens e mostrar a lista, mas quebra com AttributeError na segunda pergunta. Conserte a linha do append. (O editor vai digitar ovos, pão e leite por você.)
compras = []
for i in range(3):
item = input("Item: ")
compras = compras.append(item)
print(compras)
compras = []
for i in range(3):
item = input("Item: ")
compras.append(item)
print(compras)
Resumo
append(x)põe um item no fim; é o jeito mais usado de encher uma lista que começou com[].insert(i, x)põe o item no índicei; os outros andam para a direita.insert(-1, x)põe antes do último.extend(outra)e+=põem os itens de outra lista no fim;appendde uma lista põe a lista inteira como um item só.lista + outracria uma lista nova e não muda nenhuma das duas.- Os métodos que alteram a lista devolvem
None: nunca escrevalista = lista.append(x). 'NoneType' object has no attribute 'append'quer dizer que a variável recebeuNoneantes; procure o=com um método de lista.- Texto no
extendou no+=vira letras soltas.