Listas
Listas são um tipo de variável que permite o armazenamento de vários valores, que podem ser acessados por um índice. Listas são mutáveis, o que significa que seu conteúdo pode ser alterado durante a execução do programa, ou seja, itens podem ser adicionados ou removidos. Uma lista pode conter zero ou mais elementos de um mesmo tipo (duplicados ou não) ou de tipos diversos, podendo inclusive conter outras listas. O tamanho de uma lista é igual à quantidade de elementos que ela contém.
Veja como é simples criar uma lista com alguns números inteiros:
Na primeira linha, usamos colchetes ([]
) para criar uma lista que contém três elementos e, em seguida, atribuímos à variável N
(dizemos que o tamanhos da lista N
é 3). Na segunda linha, a lista é impressa através do nome da variável. Todos os elementos são impressos na mesma ordem em que foram armazenados na lista.
Aqui está outra lista que contém três strings:
Como dito, uma lista pode conter elementos de um mesmo tipo ou de tipos diversos. Por exemplo:
Note que a lista notas
contém elementos repetidos e a lista info
contém elementos de diferentes tipos.
Os colchetes vazios ([]
) e a função de list()
podem ser usados para criar listas vazias que não possuem nenhum elemento.
Tamanho de uma lista
Às vezes, precisamos saber quantos elementos existem em uma lista. Existe uma função integrada chamada len
que pode ser aplicada a qualquer sequência e retorna o seu tamanho. Portanto, quando aplicado a uma lista, ela retorna o número de elementos dessa lista.
Índices
Uma maneira de acessar os elementos individuais de uma lista (assim como cada caractere em uma string) é através do índice. Cada elemento em uma lista possui um índice que especifica sua posição na lista. O índice começa em 0, portanto, o índice do primeiro elemento é 0, o índice do segundo elemento é 1 e assim por diante. O índice do último elemento em uma lista é 1 menos que o número de elementos na lista.
Para acessar um elemento de uma lista por seu índice, precisamos usar colchetes. Adicionamos os colchetes após a lista e, entre eles, escrevemos o índice de um elemento que desejamos obter. Veja um exemplo:
Lembre-se que os índices começam em 0 e, portanto, o índice do último elemento é igual a len(lista) - 1
. Assim, tentar acessar uma posição maior que o número de elementos da lista menos 1 gera um erro (IndexError
). Por exemplo:
Em Python, também é possível usar índices negativos com listas para identificar as posições dos elementos em relação ao final da lista. O índice -1
identifica o último elemento em uma lista, -2
identifica o penúltimo elemento e assim por diante. Nesse caso, o primeiro elemento de uma lista também pode ser acessado usando -len(lista)
. O código a seguir mostra um exemplo:
A figura abaixo mostra o conceito geral de índices em uma lista:
Como já dito, as listas em Python são mutáveis, o que significa que seus elementos podem ser alterados. Utilizando o nome da lista e um índice, podemos mudar o conteúdo de um elemento. Por exemplo:
Incluindo elementos
Uma alternativa para incluir elementos em uma determinada lista é utilizando o método append()
. Ele faz com que o elemento seja adicionado no final da lista. A sua sintaxe básica é a seguinte:
onde <lista>
é o nome da variável do tipo lista e <elemento>
é o elemento que deve ser incluído no fim da lista. Veja um exemplo:
Veja outro exemplo em que é feita a leitura de notas de uma turma enquanto não for digitado um valor negativo.
Outra forma de incluir elementos em uma lista é utilizando o método insert()
. A diferença desse método para o append()
é que você especifica em qual índice deseja incluir o novo elemento. Observe a sintaxe básica:
Veja um exemplo:
Se o índice do insert()
foi maior que o tamanho da lista, o elemento será incluído no fim da mesma.
Removendo elementos
Para remover elementos de uma lista, existem os métodos remove()
e pop()
e a função del
. As sintaxes básicas de cada uma dessas maneiras de remover elementos de uma lista são mostradas a seguir:
-
Método
remove(<elemento>)
: remove o<elemento>
da lista passado como parâmetro para o método. Se na lista existir mais de um elemento com o valor informado, será removido apenas a primeira ocorrência encontrada. Exemplos: -
Método
pop(<índice>)
: remove o elemento da posição<índice>
. Se o índice não for informado, o método removerá o último elemento da lista. Exemplos: -
Função
del <lista>[<índice>]
: função integrada que remove o elemento da posição<índice>
de<lista>
. Se não for informado o índice da lista que se deseja remover o elemento, a funçãodel
destruirá a variável do tipo lista. Exemplos:
Por fim, se desejarmos esvaziar uma lista, podemos utilizar o método clear()
, cuja sintaxe básica é a seguinte:
Operador in
Quando precisamos verificar se determinado valor está em uma lista ou string, podemos usar o operador booleano in
presente em Python. Tal operador retorna True
se o elemento estiver na estrutura e False
, caso contrário. Quando precisamos verificar se um valor não está em uma lista/string, podemos usar o operador not in
. Se uso é bem simples:
Observe que o operador in
é equivalente ao operador pertence da matemática (\(\in\)). Vejamos mais um exemplo:
def main():
vogais = ['a', 'e', 'i', 'o', 'u']
l = input("Digite uma letra: ")
print("Vogal" if l in vogais else "Consoante")
print("Consoante" if l not in vogais else "Vogal")
main()
Outro exemplo:
def main():
alunosMatriculados = ['Paulo', 'Andre', 'Julio']
aluno = input("Digite o nome do aluno: ")
if aluno in alunosMatriculados:
print(f"Aluno {aluno} está matriculado")
else:
print(f"Aluno {aluno} não está matriculado")
main()
Percorrendo uma lista
Quando uma lista possui poucos elementos, podemos acessar cada um de forma bem simples. Entretanto, quando uma lista possui vários elementos e precisamos imprimir ou fazer alguma análise/cálculo com os elementos precisamos de uma forma de acessar todos os elementos. Por exemplo, imagine que você tenha uma lista com a medida da temperatura de 365 dias e deseja saber (\(i\)) a temperatura média, (\(ii\)) a temperatura máxima, (\(iii\)) a temperatura mínima, (\(iv\)) o desvio padrão das temperaturas, (\(v\)) quantos dias a temperatura ficou acima (ou abaixo) da temperatura média, (\(vi\)) quais dias que a temperatura foi a máxima, etc. Note que para fazer essas operações temos que percorrer/acessar todos os elementos da lista. Para isso podemos utilizar o loop while
ou for
.
Usando while
Uma das formas de acessarmos cada um dos elementos da lista é iterando sobre os índices dos itens da lista, ou seja, primeiro acessamos o elemento da posição 0
, depois da 1
, e assim por diante, até o elemento de índice len(lista) - 1
. Usando o loop while
precisamos de uma variável que irá representar o índice que estamos acessando a lista em determinada iteração. O exemplo abaixo percorre a lista disciplinas
e imprime, em cada linha, os elementos de tal lista.
Pergunta
Por que a condição do loop while
anterior foi i < len(disciplinas)
e não i <= len(disciplinas)
?
Usando for
Python apresenta uma estrutura de repetição especialmente projetada para
percorrer listas. A instrução for
funciona de forma parecida a while
, mas a cada repetição utiliza um elemento diferente da lista. A instrução for
itera sobre os itens de qualquer iterável (lista
, tupla
, dicionário
, set
ou string
). Os itens são iterados na ordem em que aparecem no iterável. A sintaxe da instrução for
é bem simples:
Fonte: Learn Python By Example
Na instrução for
, <iterável>
é uma coleção de objetos — por exemplo, uma lista ou tupla ou string. O corpo do loop é indicado pela indentação, como acontece com todas as estruturas de controle em Python e é executado uma vez para cada item em <iterável>
. A variável de loop <var>
assume o valor do próximo elemento em <iterável>
cada vez que passa pelo loop. Veja um exemplo de um programa que imprime todos os elementos de uma lista:
Embora a instrução for
facilite nosso trabalho, ela não substitui completamente while
. Dependendo do problema, utilizaremos for
ou while
. Normalmente utilizaremos for
quando quisermos processar os elementos de uma lista, um a um. while
é indicado para repetições nas quais não sabemos ainda quantas vezes vamos repetir ou onde manipulamos os índices de forma não sequencial.
Também podemos usar as instruções break
e continue
no loop for
.
Função range
Podemos utilizar a função integrada range()
para gerar uma lista/sequência de números entre o intervalo fornecido. A função range
não retorna uma lista propriamente dita, mas um gerador ou generator. Por enquanto, basta entender como podemos usá-la. Veja um exemplo:
A função range
gerou números de 0 a 4 porque passamos 5 como parâmetro. Ela normalmente gera valores a partir de 0, logo, ao especificarmos apenas 5, estamos apenas informando onde parar.
A função range()
pode receber no máximo três argumentos:
- Os parâmetros
start
estep
emrange()
são opcionais.
Onde start
indica o valor inicial da sequência (parâmetro opcional cujo valor padrão é 0
), stop
valor final da sequência (parâmetro obrigatório), step
representa o incremento da sequência (parâmetro opcional cujo valor padrão é 1
).
-
range(stop)
Ao chamarrange()
com apenas um argumento, teremos uma sequência de números de 0 até o número especificado.Observe que
range(7)
não são os valores de 0 a 7, mas sim os valores de 0 a 6. -
range(start, stop)
Por padrão, a funçãorange()
inicia o intervalo em 0. No entanto, podemos iniciar o intervalo com outro número adicionando o valor do parâmetrostart
. -
range(start, stop, step)
Por padrão, na funçãorange()
o intervalo é incrementado em 1. No entanto, podemos especificar um incremento diferente adicionando o valor do parâmetrostep
.Podemos percorrer os números na ordem inversa (decrementando) especificando um valor negativo para
step
.
A função range
retorna uma sequência imutável de números que pode ser facilmente convertida em listas, tuplas, etc. Para isso, utilizamos a função list()
:
Função enumerate
Muitas vezes precisamos percorrer uma lista e obter, simultaneamente, seus elementos e os respectivos índices. Para isso, podemos utilizar a função enumerate()
que, em geral, também é combinada com a estrutura de repetição for
. Tal função gera uma tupla em que o primeiro valor é o índice e o segundo é o elemento da lista sendo enumerada. Veja como se pode utilizar enumerate()
dentro de um for
.
Veja um exemplo:
Como dito, a função enumerate()
gera uma tupla. Veja o que acontece se usarmos apenas uma variável no for
:
Embaralhando e Sorteando Elementos
Em algumas situações, é necessário escolher aleatoriamente um elemento dentro de uma lista. Um caso clássico dessa situação é um sorteio. Contudo, antes de realizar um sorteio, é realizado um embaralhamento das suas possíveis opções.
Para embaralhar os elementos de uma lista, utilizamos a função shuffle(<lista>)
que, antes de ser executado, necessita que a biblioteca random
seja importada. Para sortear um dos elementos da lista, utilizamos a função choice(<lista>)
. Veja um exemplo:
Ordenando elementos
Para ordenar elementos de uma lista podemos usar o método sort()
, cuja sintaxe básica é a seguinte:
onde o argumento reverse indica se haverá inversão (reverse = True
) ou se não haverá (reverse = False
). Por padrão, o valor desse parâmetro é False
(ordenação crescente) e, portanto, o argumento reverse
pode ser omitido. Veja um exemplo:
Também podemos usar a função integrada sorted
para obter uma cópia ordenada de uma lista, sem alterar a lista original.
Concatenando listas
Podemos usar o operador +
para concatenar (juntar) duas listas. Por exemplo:
Também podemos usar o operador de atribuição +=
para concatenar uma lista a outra. Por exemplo:
Quando precisamos replicar uma lista n vezes, podemos usar o operador *
(que funciona de forma equivalente com string).
Vejamos um exemplo simples de como podemos fazer a leitura de duas notas:
Note que se o número de notas a ser lido for grande ou se não soubermos a quantidade de notas, devemos usar uma estrutura de repetição para ler as notas e retornar uma lista com as notas.
Vamos fazer uma função que receba a quantidade de notas a ser lida e retorna uma lista de notas, usando concatenação.
A função leNotas
pode ser feita de diversas outras maneiras. Pense em outras formas de implementar tal função.
Exercício
Modifique a função para que as notas sejam lidas enquanto não for digitado um valor negativo.
Fatiamento
Com a indexação podemos selecionar um elemento específico em uma lista. Entretanto, às vezes, precisamos selecionar mais de um elemento de uma lista. Em Python, podemos escrever expressões que selecionam sublistas de uma lista, conhecidas como fatias.
Uma fatia é um intervalo de itens retornados de uma lista. Quando pegamos uma fatia de uma lista, obtemos um intervalo de elementos da lista. Se L
for uma lista, a expressão L[<inicio>:<fim>:<salto>]
retorna a parte da lista do índice <inicio>
até o índice <fim>
, saltando <salto>
elementos. O parâmetro <salto>
é opcional e, por padrão, vale 1.
No formato geral, <inicio>
é o índice do primeiro elemento do fatiamento e <fim>
é o índice que marca o fim da fatia. A expressão retorna uma lista contendo uma cópia dos elementos desde o <inicio>
até (mas não incluindo) o <fim>
. Por exemplo:
A figura abaixo ilustra a operação L[2:7]
:
Fonte: Learn Python By Example
Note que o item no índice 7 (que contém 'h'
) não está incluído no fatiamento anterior.
Se você deixar em branco o valor de <inicio>
em um fatiamento, será usado 0
como o índice inicial. Veja alguns exemplos:
Se você deixar em branco o valor de <fim>
em um fatiamento, será usado o tamanho da lista como o índice final. Por exemplo:
Se você deixar em branco o valor de <inicio>
e <fim>
em um fatiamento, você obterá uma cópia da lista inteira. Exemplo:
Os exemplos de fatiamento que vimos até agora obtêm fatias de elementos consecutivos das listas. Expressões de fatiamento também podem ter um valor de "salto" (step), o que pode fazer com que algumas posições sejam ignoradas na lista. Por exemplo:
Fonte: Learn Python By Example
Vejamos mais alguns exemplos:
Vale destacar que índices inválidos em um fatiamento não geram erros. Por exemplo:
-
Se o índice final for uma posição além do final da lista, será usado o tamanho da lista:
-
Se o índice inicial for uma posição antes do início da lista, será usando o valor 0:
-
Se o índice inicial for maior que o índice final, a expressão fatiada retornará uma lista vazia:
Cópia de listas
Um dos efeitos colaterais de lista aparece quando tentamos fazer cópias. Por exemplo:
Veja que, ao modificarmos V
, modificamos também o conteúdo de L
. Isso porque uma lista em Python é um objeto e, quando atribuímos um objeto a outro, estamos apenas copiando a mesma referência da lista, e não seus dados. Nesse caso, V
funciona como um apelido de L
, ou seja, V
e L
são a mesma lista. Dessa forma, quando modificamos V[0]
, estamos modificando o mesmo valor de L[0]
, pois ambos são referências, ou apelidos, para a mesma lista na memória.
Dependendo da aplicação, esse efeito pode ser desejado ou não. Para criarmos uma cópia independente de uma lista, temos três alternativas:
- Concatenação com uma lista vazia (
[]
):
- Fatiamento:
Ao escrevermos L[:]
, estamos nos referindo a uma nova cópia de L
(lembre-se que fatiamento sempre retorna uma cópia). Assim, L
e V
se referem a áreas diferentes na memória, permitindo alterá-las de forma independente.
- Método
copy()
:
Listas aninhadas
Uma lista pode conter qualquer objeto, até mesmo outra lista (sublista), que por sua vez pode conter as outras sublistas e assim por diante. Isso é conhecido como lista aninhada (do inglês, nested list). Você pode usá-las para organizar os dados em estruturas hierárquicas. Por exemplo:
Podemos acessar itens individuais em uma lista aninhada usando os subíndices. Os índices para os itens da lista aninhada anterior são ilustrados a seguir:
Fonte: Learn Python By Example
Podemos modificar o valor de um item específico em uma lista aninhada através do índice.
Para adicionar um novo elemento no fim de uma lista aninhada, podemos usar o método append()
.
A função integrada len()
também é usada para descobrir quantos itens uma sublista aninhada possui:
Se precisarmos percorrer todos os elementos de uma lista aninhada, podemos usar um loop for
:
Perceba que em cada linha foi impresso uma lista. Normalmente, queremos acessar cada uma dos elementos da lista aninhada de forma "independente". Para isso, precisamos ter um for
aninhado que fica responsável por iterar sobre os elementos de cada sublista:
Outra alternativa usando a função range()
:
Compreensão de listas
Compreensão de listas (list comprehensions) é uma maneira elegante e compacta de criar listas com base em listas existentes.
Vejamos um exemplo, suponha que precisamos criar uma lista de todos os números inteiros quadrados de 0 a 4. Podemos construir essa lista incluindo um item de cada vez a uma lista vazia:
Outra alternativa é usar um loop:
Aqui ambas as abordagens produzem o mesmo resultado. No entanto, uma maneira mais Pythonica de construir uma lista é usando uma compreensão de lista.
A sintaxe geral para a compreensão de lista é:
Fonte: Learn Python By Example
Veja como podemos usar compreensão de lista para construir a lista anterior:
Abaixo são apresentados outros exemplos de compreensão de listas.
-
Compreensão de lista pode iterar em qualquer tipo de iterável, como listas e strings. Veja um exemplo de uma compreensão de lista simples que usa string como um iterável.
-
O exemplo a seguir aplica a função
abs()
a todos os elementos em uma lista. -
O exemplo abaixo cria uma lista, usando expressão ternária, onde a posição
i
contém a string"Par"
se i for par e"Impar"
, caso contrário. -
O exemplo abaixo cria uma lista contendo a raiz quadrada de cada número.
Note que nesse exemplo, primeiro foi criado uma lista (usando compreensão de lista) aplicando a função
abs()
em cada elemento de[-4, -16 , -64 , -256]
. Dessa forma, teremos a lista[4, 16 , 64 , 256]
. Com essa última lista é aplicado a função raiz quadrada (math.sqrt()
). -
O exemplo abaixo faz a leitura de vários valores da entrada, digitados na mesma linha, e cria uma lista com cada valor convertido para inteiro.
-
O exemplo abaixo cria uma lista aninhada onde cada elemento é uma lista da forma
[x, x**2]
, para \(0 \leq x \leq 5\).
Compreensão de lista com cláusula if
Uma compreensão de lista pode ter uma cláusula if
opcional associada para filtrar itens do resultado. Os itens do iterável para os quais a cláusula if
não é verdadeira são ignorados. A sintaxe é bem simples:
Fonte: Learn Python By Example
Vejamos alguns exemplos:
-
Dada uma lista com diversos valores inteiros, criar uma lista com apenas os elementos maiores ou iguais a zero de tal lista.
-
Dada uma lista com diversos valores de tipos variados, criar uma lista onde os elementos inteiros de tal lista são elevados ao quadrado.
Listas e funções puras
Como as variáveis do tipo list
são mutáveis, devemos tomar alguns cuidados ao usar funções que contém uma ou mais listas como parâmetros e que modificam essa(s) lista(s). Vamos a um exemplo:
Note que após a chamada da função modificaLista
, a lista L
sofreu uma alteração externa, ou seja, a alteração feita em modificaLista
persistiu após a chamada da função (efeito colateral). De forma resumida, isso acontece porque Python passa o endereço da memória onde a lista está armazenada e não uma cópia dela (como acontece com as variáveis do tipo int
e float
, por exemplo). Por isso, modificaLista
é considerada uma função impura. O mesmo acontece com a função adicionaElemento
. Para não restar dúvidas, teste o código no Python Tutor.
Note que tanto a lista L
(da função main
) quanto lista
(das funções modificaLista
e adicionaElemento
) "apontam" para o mesmo objeto, ou seja, se modificamos um, iremos modificar o outro também. Dessa forma, a modificação nas funções modificaLista
e adicionaElemento
persiste após a execução da função, o que vai contra a ideia de funções puras.
Para resolvermos esse "problema", basta passar uma cópia da lista para a função, ou seja, devemos chamar a função da seguinte forma: modificaLista(L[:], 1, 45)
e adicionaElemento(L[:], 23)
(ou modificaLista(L.copy(), 1, 45)
e adicionaElemento(L.copy(), 23)
). Teste o código modificado no Python Tutor e veja o resultado.
Agora temos duas listas independentes, consequentemente, a modificação na função modificaLista
e/ou adicionaElemento
não persiste após a execução da função.
Métodos em listas
Abaixo são listados os métodos dos objetos do tipo lista:
Método | Descrição |
---|---|
append() | Adiciona um item ao final da lista |
insert() | Insere um item em uma determinada posição |
extend() | Estende a lista anexando todos os itens do iterável |
remove() | Remove a primeira instância do item especificado |
pop() | Remove o item na posição especificada na lista |
clear() | Remove todos os itens da lista |
copy() | Retorna uma cópia da lista |
count() | Retorna a contagem do item especificado na lista |
index() | Retorna o índice da primeira instância do item especificado |
reverse() | Inverte os itens da lista |
sort() | Ordena os itens da lista |
Funções integradas para listas
Python também possui um conjunto de funções integradas que podemos usar com objetos do tipo lista.
Método | Descrição |
---|---|
all() | Retorna True se todos os itens da lista forem verdadeiros |
any() | Retorna True se algum item da lista for verdadeiro |
enumerate() | Pega uma lista e retorna um objeto enumerado |
len() | Retorna o número de itens da lista |
list() | Converte um iterável (tupla, string, set etc.) em uma lista |
max() | Retorna o maior item da lista |
min() | Retorna o menor item da lista |
sorted() | Retorna uma lista ordenada |
sum() | Soma os itens da lista |