S04 - Atividade de Aprendizagem (1 de 2): Listas
Durante esta aula, você aprenderá como armazenar vários elementos em uma lista Python. Você aprenderá a escrever um loop que processa cada elemento de uma lista. Além disso, você aprenderá que listas são passadas para uma função de forma diferente de números.
Vídeos
Assista a esse vídeo sobre coleções:
Conceitos
Aqui estão os conceitos e assuntos de programação em Python que você deve aprender durante esta aula:
Listas
Um programa Python pode armazenar muitos valores em uma lista. As listas são mutáveis, então podem ser alteradas depois de serem criadas. Cada valor em uma lista é chamado de elemento, e é armazenado em um índice exclusivo. Um índice é sempre um número inteiro e determina onde um elemento é armazenado em uma lista. O primeiro índice de uma lista Python é sempre zero. O diagrama a seguir mostra uma lista que contém cinco strings. O diagrama mostra os elementos e os índices da lista. Observe que cada índice é um inteiro único e que o primeiro índice é zero.
| elemento | "amarelo" | "vermelho" | "verde" | "amarelo" | "azul" |
| índices | [0] | [1] | [2] | [3] | [4] |
| ← o comprimento da lista é 5 → | |||||
Em um programa Python, é possível criar uma lista usando colchetes ([ e ]). Podemos determinar o número de itens em uma lista chamando a função embutida len. Podemos recuperar um item de uma lista e substituir um item em uma lista usando colchetes ([ e ]) e um índice. O exemplo 1 contém um programa que cria uma lista, exibe o comprimento dessa lista, recupera e exibe um item dela, altera um item e, em seguida, exibe a lista inteira.
# Exemplo 1
def main():
# Cria uma lista que contém cinco strings.
cores = ["amarelo", "vermelho", "verde", "amarelo", "azul"]
# Chama a função embutida len
# e exibe o comprimento da lista.
comprimento = len(cores)
print(f"Número de elementos: {comprimento}")
# Exibe o elemento que está armazenado
# no índice 2 na lista de cores.
print(cores[2])
# Altera o elemento que está armazenado no
# índice 3 de "amarelo" para "roxo".
cores[3] = "roxo"
# Exibe a lista de cores inteira.
print(cores)
# Chama main para iniciar este programa.
if __name__ == "__main__":
main()
> python exemplo_1.py Número de elementos: 5 verde ['amarelo', 'vermelho', 'verde', 'roxo', 'azul']
Podemos adicionar um item a uma lista usando os métodos insert e append. Podemos determinar se um elemento está em uma lista usando o operador de associação Python, que é a palavra-chave in. Podemos encontrar o índice de um item dentro de uma lista usando o método index. Podemos remover um item de uma lista usando os métodos pop e remove. O exemplo 2 mostra como criar uma lista e adicionar, localizar e remover itens da lista.
# Exemplo 2
def main():
# Cria uma lista vazia que conterá nomes de tecidos.
tecidos = []
# Adiciona três elementos no final da lista de tecidos.
tecidos.append("veludo")
tecidos.append("denim")
tecidos.append("algodão fino")
# Insere um elemento no início da lista de tecidos.
tecidos.insert(0, "chiffon")
print(tecidos)
# Determina se algodão fino está na lista de tecidos.
if "algodão fino" in tecidos:
print("algodão fino está na lista.")
else:
print("algodão fino NÃO está na lista.")
# Obtém o índice em que veludo está armazenado na lista de tecidos.
i = tecidos.index("veludo")
# Substitui veludo por tafetá.
tecidos[i] = "tafetá"
# Remove o último elemento da lista de tecidos.
tecidos.pop()
# Remove denim da lista de tecidos.
tecidos.remove("denim")
# Obtém o comprimento da lista de tecidos e exibe-a.
n = len(tecidos)
print(f"A lista de tecidos contém {n} elementos.")
print(tecidos)
# Chama main para iniciar este programa.
if __name__ == "__main__":
main()
> python exemplo_2.py ['chiffon', 'veludo', 'denim', 'algodão fino'] algodão fino está na lista. A lista de tecidos contém 2 elementos. ['chiffon', 'tafetá']
As listas nos exemplos 1 e 2 armazenam strings. Também é possível armazenar números em uma lista. Na verdade, Python permite que um programa armazene qualquer tipo de dado em uma lista, incluindo outras listas.
Repetição
Um programador pode fazer com que um computador repita um grupo de instruções ao escrever loops for e while.
Loop For
Um loop for itera sobre uma sequência, como uma lista. Isso significa que um loop for faz com que o computador execute repetidamente as instruções no corpo do loop for, uma vez para cada elemento na sequência. No exemplo 3, considere a lista de cores na linha 4 e o loop for nas linhas 6–7. Observe como o loop for faz com que o computador repita a linha 7 uma vez para cada elemento na lista cores. É importante observar que o código no corpo de um loop pode fazer muito mais com cada elemento do que simplesmente exibi-lo.
# Exemplo 3
def main():
# Cria uma lista de nomes de cores.
cores = ["vermelho", "laranja", "amarelo", "verde", "azul"]
# Usa um loop for para exibir cada elemento na lista.
for cor in cores:
print(cor)
# Chama main para iniciar este programa.
if __name__ == "__main__":
main()
> python exemplo_3.py vermelho laranja amarelo verde azul
Observe no exemplo 3, nas linhas 6–7, que assim como nas instruções if em Python, o corpo de um loop começa e termina com recuo.
Função range
A função embutida range do Python cria e retorna uma sequência de números. Ela aceita um, dois ou três parâmetros, conforme mostrado no exemplo 4 e sua saída. Muitos programadores usam a função range em um loop for para fazer com que o computador repita o código uma vez para cada número em um intervalo de números. O exemplo 4 mostra quatro loops for que iteram em um intervalo de números.
# Exemplo 4
def main():
# Conta de zero a nove de um em um.
for i in range(10):
print(i)
print()
# Conta de cinco a nove de um em um.
for i in range(5, 10):
print(i)
print()
# Conta de zero a oito de dois em dois.
for i in range(0, 10, 2):
print(i)
print()
# Conta de 100 a 70 de três em três.
for i in range(100, 69, -3):
print(i)
# Chama main para iniciar este programa.
if __name__ == "__main__":
main()
> python exemplo_4.py 0 1 2 ⋮ 8 9 5 6 7 8 9 0 2 4 6 8 100 97 94 ⋮ 73 70
No exemplo 5, nas linhas 6–7 e 11–15, há dois loops for. Ambos os loops exibem cada elemento de uma lista chamada cores. O primeiro loop itera sobre os elementos na lista de cores. O segundo loop usa as funções embutidas len e range para iterar sobre os índices da lista cores. Qual estilo de loop for você prefere ler e escrever? A maioria dos programadores prefere escrever um loop como o das linhas 6–7 porque é mais simples que o das linhas 11–15.
# Exemplo 5
def main():
# Cria uma lista de nomes de cores.
cores = ["vermelho", "laranja", "amarelo", "verde", "azul"]
# Usa um loop for para exibir cada elemento na lista.
for cor in cores:
print(cor)
print()
# Usa um loop for diferente para
# exibir cada elemento na lista.
for i in range(len(cores)):
# Usa o índice i para recuperar
# um elemento da lista.
cor = cores[i]
print(cor)
# Chama main para iniciar este programa.
if __name__ == "__main__":
main()
> python exemplo_5.py vermelho laranja amarelo verde azul vermelho laranja amarelo verde azul
No exemplo anterior, o código no corpo de ambos os loops for é muito curto e simplesmente exibe um elemento da lista a cada execução do loop. No entanto, você pode escrever quantas linhas de código forem necessárias no corpo de um loop para executar repetidamente todos os tipos de cálculos para cada elemento em uma lista.
Instrução break
Uma instrução break faz com que um loop termine mais cedo. No exemplo 6, nas linhas 6–10, há um loop for que solicita ao usuário que insira dez números, um de cada vez. Entretanto, o loop terminará mais cedo se o usuário digitar zero (0) por causa da instrução if e break nas linhas 8 e 9.
# Exemplo 6
def main():
sum = 0
# Obtém ao menos dez números do usuário e soma-os.
for i in range(10):
numero = float(input("Por favor, digite um número: "))
if numero == 0:
break
sum += numero
# Exibe a soma dos números para o usuário.
print(f"soma: {sum}")
# Chama main para iniciar este programa.
if __name__ == "__main__":
main()
> python exemplo_6.py Por favor, digite um número: 6 Por favor, digite um número: 4 Por favor, digite um número: -2 Por favor, digite um número: 0 soma: 8.0
Loop While
Um loop while é mais flexível que um loop for e se repete enquanto alguma condição for verdadeira. Imagine que precisamos de uma função para comparar o conteúdo de duas listas? Podemos usar um loop para comparar o conteúdo de duas listas? O exemplo 7 contém um loop while nas linhas 28-40 com uma instrução if na linha 34 que encontra o primeiro índice onde duas listas diferem.
# Exemplo 7
def main():
lista1 = ["vermelho", "laranja", "amarelo", "verde", "azul"]
lista2 = ["vermelho", "laranja", "verde", "verde", "azul"]
indice = comparar_listas(lista1, lista2)
if indice == -1:
print("O conteúdo da lista1 e lista2 é igual")
else:
print(f"lista1 e lista2 diferem no índice {indice}")
def comparar_listas(lista1, lista2):
"""Compara o conteúdo de duas listas. Se o conteúdo
das duas listas não for igual, retorna o índice em que há a
primeira diferença. Se o conteúdo das duas listas
for igual, retorna -1.
Parâmetros
lista1: uma lista
lista2: outra lista
Retorna: um índice ou -1
"""
# Obtém o comprimento da menor lista.
comprimento1 = len(lista1)
comprimento2 = len(lista2)
limite = min(comprimento1, comprimento2)
# Começa do primeiro índice (0) e repete até que o
# programa encontre dois elementos diferentes ou
# até alcançar o fim da menor lista, o que ocorrer primeiro.
i = 0
while i < limite:
# Recupera um elemento de cada lista.
elemento1 = lista1[i]
elemento2 = lista2[i]
# Se os dois elementos forem
# diferentes, sai do loop while.
if elemento1 != elemento2:
break
# Adiciona um à variável de índice.
i += 1
# Se os comprimentos das duas listas forem iguais e
# todos os elementos forem iguais, define i como -1
# para indicar que o conteúdo das duas listas é igual.
if comprimento1 == comprimento2 == i:
i = -1
return i
# Chama main para iniciar este programa.
if __name__ == "__main__":
main()
> python exemplo_7.py lista1 e lista2 diferem no índice 2
Listas Compostas
Uma lista composta é uma lista que contém outras listas. Listas compostas são usadas para armazenar muitos dados relacionados. O exemplo 8 mostra como criar uma lista composta, recuperar uma lista interna da lista composta e recuperar um número individual da lista interna.
# Exemplo 8
def main():
# Estes são os índices de cada
# elemento nas listas internas.
INDICE_ANO_PLANTIO = 0
INDICE_ALTURA = 1
INDICE_CIRCUNFERENCIA = 2
INDICE_QUANTIDADE_FRUTOS = 3
# Cria uma lista composta que armazena listas internas.
dados_macieiras = [
# [ano_plantado, altura, circunferência, quantidade_frutos]
[2012, 2.7, 3.6, 70.5],
[2012, 2.4, 3.7, 81.3],
[2015, 2.3, 3.6, 62.7],
[2016, 2.1, 2.7, 42.1]
]
# Recupera uma lista interna da lista composta.
uma_arvore = dados_macieiras[2]
# Recupera um valor da lista interna.
altura = uma_arvore[INDICE_ALTURA]
# Exibe a altura da árvore.
print(f"altura: {altura}")
# Chama main para iniciar este programa.
if __name__ == "__main__":
main()
> python exemplo_8.py altura: 2.3
O exemplo 9 mostra como processar todos os elementos em uma lista composta. O loop for na linha 20 faz com que o computador repita as linhas 21–27 uma vez para cada lista interna que está dentro da lista composta chamada dados_macieira. A linha 23 recupera a quantidade de frutas de uma lista interna e, então, a linha 27 adiciona uma quantidade de frutas à quantidade total de frutas.
# Exemplo 9
def main():
# Estes são os índices de cada
# elemento nas listas internas.
INDICE_ANO_PLANTIO = 0
INDICE_ALTURA = 1
INDICE_CIRCUNFERENCIA = 2
INDICE_QUANTIDADE_FRUTOS = 3
# Cria uma lista composta que armazene listas internas.
dados_macieira = [
# [ano_plantado, altura, circunferência, quantidade_frutos]
[2012, 2.7, 3.6, 70.5],
[2012, 2.4, 3.7, 81.3],
[2015, 2.3, 3.6, 62.7],
[2016, 2.1, 2.7, 42.1]
]
quantidade_total_frutos = 0
# Este loop será repetido uma vez para cada lista interna
# na lista composta dados_macieira.
for lista_interna in dados_macieira:
# Recupera a quantidade de frutas da lista interna atual.
quantidade_de_frutas = lista_interna[INDICE_QUANTIDADE_FRUTOS]
# Exibe a quantidade de frutas da árvore atual.
print(quantidade_de_frutas)
# Adiciona a quantidade atual de frutas ao total.
quantidade_total_frutos += quantidade_de_frutas
# Exibe a quantidade total de frutas.
print(f"Quantidade total de frutas: {quantidade_total_frutos:.1f}")
# Chama main para iniciar este programa.
if __name__ == "__main__":
main()
> python exemplo_9.py 70.5 81.3 62.7 42.1 Quantidade total de frutas: 256.6
Valores e Referências
Em um programa Python, o computador atribui valores às variáveis de forma diferente com base no seu tipo de dados. Considere o pequeno programa do exemplo 10 e a saída desse programa. O programa no exemplo 10 contém duas variáveis inteiras chamadas x e y, e realiza as seguintes operações:
-
A instrução na linha 3 armazena o valor 17 na variável x.
-
A linha 4 copia o valor que está na variável x para a variável y.
-
A linha 5 exibe os valores de x e y, que são ambos 17.
-
A linha 6 adiciona um ao valor de x, tornando seu valor 18 em vez de 17.
-
A linha 7 exibe os valores de x e y novamente. O valor de x foi alterado para 18. O valor de y permaneceu inalterado.
Por que a linha 6 (x += 1) altera o valor de x, mas não o valor de y? Porque a linha 4 copia o valor que estava em x para y. Em outras palavras, x e y são duas variáveis separadas, cada uma com seu próprio valor.
# Exemplo 10
def main():
x = 17
y = x
print(f"Antes de alterar x: x {x} y {y}")
x += 1
print(f"Após alterar x: x {x} y {y}")
# Chama main para iniciar este programa.
if __name__ == "__main__":
main()
> python exemplo_10.py Antes de alterar x: x 17 y 17 Após alterar x: x 18 y 17
O exemplo 11 mostra um pequeno programa Python que contém duas variáveis chamadas lx e ly, cada uma referindo-se a uma lista. Este programa é semelhante ao programa anterior, mas tem duas listas em vez de dois inteiros. A partir da saída do exemplo 11, observamos que há uma grande diferença entre a maneira como um programa Python atribui números inteiros e a maneira como ele atribui listas. O programa no exemplo 11 faz o seguinte:
-
A instrução na linha 3 cria uma lista e armazena uma referência a essa lista na variável lx.
-
A linha 4 copia a referência na variável lx para a variável ly. A linha 4 não cria uma cópia da lista, mas faz com que ambas as variáveis lx e ly se refiram à mesma lista.
-
A linha 5 exibe os valores de lx e ly. Observe que seus valores são os mesmos que esperamos por causa da linha 5.
-
A linha 6 adiciona o número 5 à lista lx.
-
A linha 7 exibe os valores de lx e ly novamente. Observe na saída que, quando lx e ly são impressos pela segunda vez, parece que o número 5 foi anexado a ambas as listas.
Por que parece que anexar o número 5 em lx também anexa o número 5 em ly? Porque lx e ly se referem à mesma lista. Na verdade, existe apenas uma lista com duas referências a essa lista. Como lx e ly se referem à mesma lista, uma alteração na lista por meio da variável lx pode ser vista por meio da variável ly.
# Exemplo 11
def main():
lx = [7, -2]
ly = lx
print(f"Antes de alterar lx: lx {lx} ly {ly}")
lx.append(5)
print(f"Após alterar lx: lx {lx} ly {ly}")
# Chama main para iniciar este programa.
if __name__ == "__main__":
main()
> python exemplo_11.py Antes de alterar lx: lx [7, -2] ly [7, -2] Após alterar lx: lx [7, -2, 5] ly [7, -2, 5]
Nos exemplos 10 e 11, aprendemos que, quando um computador executa uma instrução Python para atribuir o valor de uma variável booleana, inteira ou flutuante a outra variável (y = x), o computador copia o valor de uma variável para a outra. Entretanto, quando um computador executa uma instrução Python para atribuir o valor de uma variável de lista a outra variável (ly = lx), o computador não copia o valor, mas sim a referência para que ambas as variáveis se refiram à mesma lista na memória.
Passagem por Valor e Passagem por Referência
O fato de o computador copiar o valor de alguns tipos de dados (booleano, inteiro, flutuante) e copiar a referência para outros tipos de dados (lista e outros tipos de dados grandes) tem implicações importantes na passagem de argumentos para funções. Considere o programa Python no exemplo 12 com duas funções chamadas main e modificar_args. O programa no exemplo 12 faz o seguinte:
-
A instrução na linha 4 atribui o valor 5 a uma variável chamada x.
-
A linha 5 atribui uma lista a uma variável chamada lx.
-
A linha 6 exibe os valores de x e lx antes de serem passados para a função modificar_args.
-
A linha 9 chama a função
modificar_argse passa x e lx para essa função. -
Na função
modificar_args, a linha 22 altera o valor do parâmetro n adicionando um a ele, e a linha 23 altera o valor do parâmetro lista anexando o número 4 a ele. -
A linha 10 exibe os valores de x e lx depois que eles foram passados para a função
modificar_args. Observe na saída abaixo que o valor de x não foi alterado pela funçãomodificar_args. Entretanto, o valor de lx foi alterado pela funçãomodificar_args.
# Exemplo 12
def main():
print("main()")
x = 5
lx = [7, -2]
print(f"Antes de chamar modificar_args(): x {x} lx {lx}")
# Passa um inteiro e uma lista
# para a função modificar_args.
modificar_args(x, lx)
print(f"Após chamar modificar_args(): x {x} lx {lx}")
def modificar_args(n, lista):
"""Demonstra que o computador passa um valor
para inteiros e passa uma referência para listas.
Parâmetros
n: Um número
lista: Uma lista
Retorna: nada
"""
print(" modificar_args(n, lista)")
print(f" Antes de alterar n e lista: n {n} lista {lista}")
# Altera os valores de ambos os parâmetros.
n += 1
lista.append(4)
print(f" Após alterar n e lista: n {n} lista {lista}")
# Chama main para iniciar este programa.
if __name__ == "__main__":
main()
> python exemplo_12.py
main()
Antes de chamar modificar_args(): x 5 lx [7, -2]
modificar_args(n, lista)
Antes de alterar n e lista: n 5 lista [7, -2]
Após alterar n e lista: n 6 lista [7, -2, 4]
Após chamar modificar_args(): x 5 lx [7, -2, 4]
A partir da saída do exemplo 12, observamos que modificar um parâmetro inteiro altera o inteiro somente dentro da função chamada. Entretanto, modificar um parâmetro de lista altera a lista dentro da função chamada e dentro da função de chamada. Por quê? Porque quando um computador passa uma variável booleana, inteira ou float para uma função, ele copia o valor dessa variável para o parâmetro da função chamada. Copiar o valor de um argumento para um parâmetro é conhecido como passagem por valor. Contudo, quando um computador passa uma variável de lista para uma função, ele copia a referência para que a variável original e o parâmetro se refiram à mesma lista na memória. Copiar a referência de um argumento para um parâmetro é conhecido como passagem por referência.
Justificativa para Passagem por Referência
Por que booleanos e números são passados para uma função por valor, enquanto listas são passadas para uma função por referência? Para entender a resposta a essa pergunta, considere o trabalho que um computador teria que fazer se as listas fossem passadas por valor.
Quando um computador passa uma variável numérica (ou booleana) para uma função, o número é passado por valor, ou seja, o computador copia o valor da variável numérica para o parâmetro da função chamada. Isso funciona bem para números, pois cada variável numérica ocupa uma pequena quantidade da memória do computador. Fazer uma cópia de um número é rápido e a cópia usa uma pequena quantidade de memória.
Entretanto, uma lista pode conter milhões de elementos e, portanto, ocupar uma grande quantidade de memória do computador. Se as listas fossem passadas por valor para uma função, o computador teria que fazer uma cópia da lista cada vez que ela fosse passada para uma função. Se uma lista for grande, a cópia da lista levará um tempo relativamente longo e usará muita memória do computador para a cópia. Portanto, para tornar os programas rápidos e usar menos memória, listas (e outros tipos de dados grandes) são passados para uma função por referência.
Resumo
Nesta aula, você aprenderá a armazenar vários valores em uma lista. Cada elemento fica em um índice numérico, e o primeiro índice em Python é sempre zero (0). A função len mostra quantos elementos há na lista. O último elemento fica sempre uma posição antes do comprimento total. Para acessar ou alterar itens, use colchetes ([ e ]) com o índice. Você pode percorrer todos os elementos com um loop for. Uma lista composta é uma lista que guarda outras listas.
Você também aprenderá a diferença entre passar argumentos por valor e por referência. Números são passados por valor, ou seja, o computador copia o número para a função. Listas são passadas por referência — o computador não copia a lista, apenas compartilha o mesmo endereço. Assim, se a função alterar a lista, ela muda o conteúdo original.
Atividade
Objetivo
Reforçar sua compreensão de que números são passados para uma função por valor e listas são passadas para uma função por referência.
Declaração do Problema
Em um programa Python, quando um número é passado como argumento para uma função, o computador copia o número do argumento para o parâmetro. Em outras palavras, o parâmetro obtém uma cópia do valor que está no argumento. Contudo, quando uma lista é passada como argumento para uma função, o computador não copia a lista. Em vez disso, o computador copia uma referência à lista para o parâmetro. Isso significa que o argumento e o parâmetro se referem à mesma lista. Se uma função chamada altera uma lista que foi passada para a função, isso alterará a lista tanto na função que chama quanto na chamada, porque tanto o argumento quanto o parâmetro se referem à mesma lista.
Tarefa
Durante este ponto de verificação, você examinará e executará um programa Python que passa um número e uma lista para a função. Faça o seguinte:
-
Baixe e salve o arquivo Python passar_args.py e depois abra-o no VS Code.
-
Execute o programa
passar_args.pyno seu computador. Examine o código e a saída e responda às três perguntas a seguir:-
Em
main, há duas variáveis locais, chamadas x e lx. Na linha 14, ambas as variáveis locais são passadas para a funçãomodificar_args. Após a chamada paramodificar_argsser concluída, qual das duas variáveis locais demaina funçãomodificar_argsalterou?-
x
-
lx
-
ambas
-
nenhuma delas
-
-
Por que a função
modificar_argsNÃO é capaz de alterar a variável local x demain?-
Porque x é um número e, portanto, é passado para uma função por valor
-
Porque x é uma lista e, portanto, é passado para uma função por referência
-
-
Por que a função
modificar_argsé capaz de alterar a variável local lx demain?-
Porque lx é um número e, portanto, é passado para uma função por valor
-
Porque lx é uma lista e, portanto, é passado para uma função por referência
-
-
Exemplo de Execução
> python passar_args.py
main()
Antes de chamar modificar_args(): x 5 lx [7, -2]
modificar_args(n, lista)
Antes de alterar n e lista: n 5 lista [7, -2]
Após alterar n e lista: n 6 lista [7, -2, 4]
Após chamar modificar_args(): x 5 lx [7, -2, 4]
Links Úteis:
- Voltar para: Visão Geral da Semana | Página Inicial