https://panda.ime.usp.br/pensepy/static/pensepy/09-Listas/listas.html
Listas
Uma lista (list) em Python é uma sequência ou coleção ordenada de valores. Cada valor na lista é identificado por um índice. O valores que formam uma lista são chamados elementos ou itens. Listas são similares a strings, que são uma sequência de caracteres, no entanto, diferentemente de strings, os itens de uma lista podem ser de tipos diferentes.
Valores em uma lista
Existem várias maneiras de se criar uma nova lista. A maneira mais simples é envolver os elementos da lista por colchetes ([
e]
).
[10, 20, 30, 40] ["spam", "bungee", "swallow"]
["oi", 2.0, 5, [10, 20]]
[]
.
Como você esperaria, podemos também atribuir listas a variáveis e termos listas como parâmetro de funções.
1
2
3
4
5
6
7
8
9
10
11
vocabulario = ["iteracao", "selecao", "controle"]
numeros = [17, 123]
vazia = []
lista_mista = ["ola", 2.0, 5*2, [10, 20]]
print(numeros)
print(lista_mista)
nova_lista = [numeros, vocabulario]
print(nova_lista)
9.1.1: Uma lista só pode conter números inteiros?
Comprimento de uma lista
Da mesma forma que occore com strings, a funçãolen
retorna o comprimento de uma lista (o número de elementos na lista). Entretanto, como listas podem conter itens que são listas, é importante notar quelen
somente retorna o comprimento da lista mais externa. Em outras palavras, sublistas de uma lista são consideradas como sendo um elemento simples quando contamos o comprimento da lista.
1
2
3
4
5
uma_lista = ["ola", 2.0, 5, [10, 20]]
print(len(uma_lista))
print(len(['spam!', 1, ['Brie', 'Roquefort', 'Pol le Veq'], [1, 2, 3]]))
9.2.1: O que é impresso pelo trecho de código a seguir?
uma_lista = [3, 67, "gato", 3.14, False] print(len(uma_lista))
9.2.2: O que é impresso pelo trecho de código a seguir?
uma_lista = [3, 67, "gato", [56, 57, "cachorro"], [ ], 3.14, False] print(len(uma_lista))
Acessando os elementos
A sintaxe para acessar um elemento de uma lista é a mesma usada para acessar um caractere de um string. Nós usamos o operador de indexação ([]
– não confundir com a lista vazia). A expressão dentro dos conchetes especifica o índice. Lembrar que o índice do primeiro elemento é 0. Qualquer expressão que tenha como resultado um número inteiro pode ser usada como índice e como com strings, índices negativos indicarão elementos da direita para a esquerda ao invés de da esquerda para a direita.
1
2
3
4
5
6
7
numeros = [17, 123, 87, 34, 66, 8398, 44]
print(numeros[2])
print(numeros[9-8])
print(numeros[-2])
print(numeros[len(numeros)-1])
9.3.1: O que é impresso pelo trecho de código a seguir?
uma_lista = [3, 67, "gato", [56, 57, "cachorro"], [ ], 3.14, False] print(uma_lista[5])
9.3.2: O que é impresso pelo trecho de código a seguir?
uma_lista = [3, 67, "gato", [56, 57, "cachorro"], [ ], 3.14, False] print(uma_lista[2].upper())
9.3.3: O que é impresso pelo trecho de código a seguir?
uma_lista = [3, 67, "gato", [56, 57, "cachorro"], [ ], 3.14, False] print(uma_lista[2][0])
Pertinência em uma Lista
in
enot in
são operadores booleanos ou lógicos que testam a pertinência (membership) em uma sequência. Já usamos esses operadores com strings e eles também funcionam aqui.
1
2
3
4
5
6
frutas = ["maca", "laranja", "banana", "cereja"]
print("maca" in frutas)
print("pera" in frutas)
9.4.1: O que é impresso pelo trecho de código a seguir?
uma_lista = [3, 67, "gato", [56, 57, "cachorro"], [ ], 3.14, False] print(3.14 in uma_lista)
9.4.2: O que é impresso pelo trecho de código a seguir?
uma_lista = [3, 67, "gato", [56, 57, "cachorro"], [ ], 3.14, False] print(57 in uma_lista)
Concatenação e repetição
Novamente, como com strings, o operador+
concatena listas. Analogamente, o operador*
repete os itens em uma lista um dado número de vezes.
1
2
3
4
5
6
7
8
frutas = ["maca", "laranja", "banana", "cereja"]
print([1, 2] + [3, 4])
print(frutas + [6, 7, 8, 9])
print([0] * 4)
print([1, 2, ["ola", "adeus"]]*2)
Uma maneira de fazermos isto mais claro é executar uma parte desses exemplos no codelens. A medida que cada passo do código é executado, você verá as variáveis sendo criadas e as listas as quais elas se referem. Preste atenção particularmente ao rótulo (tag) id que é mostrado depois do descritor do tipo de dado (list (id = 12))
). Em Python o id corresponde a um único identificador para aquele objeto particular. Você pode dizer se são objetos diferentes através da comparação dos seus ids.
1 frutas = ["maca", "laranja", "banana", "cereja"] 2 num_lista = [6,7] 3 4 nova_lista = frutas + num_lista 5 6 zeros = [0] * 4 line that has just executednext line to executeFramesGlobal variablesfrutas num_lista nova_lista zeros Objectslist0 1 2 3 "maca" "laranja" "banana" "cereja" list0 1 6 7 list0 1 2 3 4 5 "maca" "laranja" "banana" "cereja" 6 7 list0 1 2 3 0 0 0 0 nova_lista = frutas + num_lista
cria uma nova lista de objetos com o contéudo da listafrutas
seguido pelo conteúdo da listanum_lista
. Podemos ver que está é uma lista nova olhando os ids. O id danova_lista
não e o mesmo que o das outras. É extremamente importante que você saiba quando está criando uma nova lista ou apenas alterando uma lista existente. Novamente, os ids podem ajudar nessa tarefa.
Python possui uma função nativa (build-in) que recebe um objeto como argumento e retorna o seu id. A função é comvenientemente chamada deid
e tem um único parâmetro, o objeto que você está interessado em descobrir o id. Você pode ver no examplo abaixo que o id real é usualmente um número inteiro muito grande (correspondente a um endereço na memória).
>>> uma_lista = [4,5,6] >>> id(uma_lista) 4300840544 >>>
9.5.1: O que é impresso pelo trecho de código a seguir?
uma_lista = [1, 3, 5] outra_lista = [2, 4, 6] print(uma_lista + outra_lista)
9.5.2: O que é impresso pelo trecho de código a seguir?
uma_lista = [1, 3, 5] print(uma_lista * 3)
Fatias de listas
A operação de fatiar (slice) que vimos com strings também pode ser aplicada sobre listas. Lembre que o primeiro índice indica o ponto do início da fatia e o segundo índice é um depois do final da fatia (o elemento com esse índice não faz parte da fatia).
1
2
3
4
5
6
7
uma_lista = ['a', 'b', 'c', 'd', 'e', 'f']
print(uma_lista[1:3])
print(uma_lista[:4])
print(uma_lista[3:])
print(uma_lista[:])
9.6.1: O que é impresso pelo trecho de código a seguir?
uma_lista = [3, 67, "gato", [56, 57, "cachorro"], [ ], 3.14, False] print(uma_lista[4:])
Listas são mutáveis
Diferentemente de strings, listas são mutáveis (mutable). Isto significa que podemos alterar um item em uma lista acessando-o diretamente como parte do comando de atribuição. Usando o operador e indexação (colchetes) à esquerda de um comando de atribuição, podemos atualizar um dos itens de uma lista.
1
2
3
4
5
6
7
8
frutas = ["banana", "maca", "cereja"]
print(frutas)
frutas[0] = "pera"
frutas[-1] = "laranja"
print(frutas)
Aqui está o mesmo exemplo com o codelens para que você possa executar comando após comando e veja as mudanças na lista de elementos.
1 frutas = ["banana", "maça", "cereja"] 2 3 frutas[0] = "pera" 4 frutas[-1] = "laranja" line that has just executednext line to executeFramesObjects
1
2
3
4
5
uma_lista = ['a', 'b', 'c', 'd', 'e', 'f']
uma_lista[1:3] = ['x', 'y']
print(uma_lista)
1
2
3
4
5
uma_lista = ['a', 'b', 'c', 'd', 'e', 'f']
uma_lista[1:3] = []
print(uma_lista)
1
2
3
4
5
6
7
uma_lista = ['a', 'd', 'f']
uma_lista[1:1] = ['b', 'c']
print(uma_lista)
uma_lista[4:4] = ['e']
print(uma_lista)
9.7.1: O que é impresso pelo trecho de código a seguir?
uma_lista = [4, 2, 8, 6, 5] uma_lista[2] = True print(uma_lista)
Remoção em listas
Usando fatiamento para remover elementos de uma lista pode ser complicado, e portanto propagador de erros. Python oferece uma maneira alternativa que é mais legível. O comandodel
remove um elemento de uma lista usando a sua posição.
1
2
3
4
5
6
7
8
9
a = ['um', 'dois', 'três']
del a[1]
print(a)
lista = ['a', 'b', 'c', 'd', 'e', 'f']
del lista[1:5]
print(lista)
del
também manipula índices negativos e produz um erro de execução se o índice estiver foram do intervalo da lista. Além disso, você pode usar uma fatia como argumento paradel
. Como é usual, fatias selecionam todos os elementos até, mas não incluindo, o segundo índice.
Objetos e referências
Se executamos as seguintes atribuições,
a = "banana" b = "banana"
a
eb
farão referência ao string"banana"
. Entretanto, ainda não sabemos se eles se referem ao mesmo string.
Existem duas possibilidades para o Python interpretar internamente essas atribuições:
ou
Em uma das interpretaçõesa
eb
se referem a dois strings ou objetos diferentes que têm o mesmo valor. Na segunda interpretação, eles se referem ao mesmo objeto. Lembre-se que um objeto é uma valor ao qual uma variável pode se referir ou apontar.
Já sabemos que objetos podem ser identificados usando seus identificadores que são únicos. Podemos também testar se dois nomes se referem ao mesmo objeto usando o operadoris
. O operador is retornaTrue
se as duas referências são ao mesmo objeto. Em outras palavras, as referências são a mesma. Teste esse conceito com os exemplos acima.
1
2
3
4
5
6
a = "banana"
b = "banana"
print(a is b)
True
. Isto nos diz que ambosa
eb
se referem ao mesmo objeto, e que o segundo dos diagramas de referências descreve a relação. Como strings são imutáveis (immutable), Python optimiza recursos fazendo dois que se referem ao mesmo string se referirem ao mesmo objeto.
Este não é o caso com listas. Considere o exemplo seguir. Aquia
eb
se referem a duas listas diferentes, cada uma por acaso tem os mesmo elementos como valores.
1
2
3
4
5
6
7
8
a = [81, 82, 83]
b = [81, 82, 83]
print(a is b)
print(a == b)
a
eb
tem o mesmo valor mas não se referem ao mesmo objeto.
Existe ainda um outro ponto importante a ser notado a respeito desse diagrama de referências. O valora
é uma referência a uma coleção de referências (collection of references). Essas referências na realidade se referem a valores inteiros em uma lista. Em outras palavras, um lista é uma coleção de referências para objetos. É interessante que apesar dea
eb
serem duas listas distintas (duas coleções de diferentes de referências), o objeto inteiro81
é compartilhado por ambos. Como strings, inteiros são também imutáveis portanto Python optimiza e permite que todos compartilhem o mesmo objeto.
Aqui esta o exemplo no codelens. Preste atenção particularmente nos valores dos id.
1 a = [81, 82, 83] 2 b = [81, 82, 83] 3 4 print(a is b) 5 print(a == b) line that has just executednext line to executeProgram output:
FramesGlobal variablesa b Objectslist0 1 2 81 82 83 list0 1 2 81 82 83 Apelidos (Aliasing)
Como variáveis fazem referência a objetos, se atribuimos uma variável a outra, ambas as variáveis passam a fazer referência ao mesmo objeto.
1
2
3
4
5
a = [81, 82, 83]
b = a
print(a is b)
Como a mesma lista tem dois nomes diferentes,a
eb
, dizemos que a lista tem apelidos (aliased). Mudanças feitas com um apelido afeta o outro. No exemplo do codelens a seguir, os ids dea
eb
são os mesmos depois da execução do comando de atribuiçãob = a
.
1 a = [81, 82, 83] 2 b = [81, 82, 83] 3 4 print(a == b) 5 print(a is b) 6 7 b = a 8 print(a == b) 9 print(a is b) 10 11 b[0] = 5 12 print(a) line that has just executednext line to executeProgram output:
FramesGlobal variablesa b Objectslist0 1 2 5 82 83
Teste seu entendimento
9.10.1: O que é impresso pelo trecho de código a seguir?
lista_a = [4, 2, 8, 6, 5] lista_b = lista_a lista_b[3] = 999 print(lista_a)
Clonando listas
Se desejamos modificar uma lista e também manter uma cópia da lista original, temos que ser capazes de fazer uma cópia da lista, não apenas da referência. Este processo é algumas vezes chamado de clonar (cloning), para evitar a ambiguidade da palavra cópia.
A maneira mais fácil de clonarmos uma lista é usar o operador de fatiação.
Tomar qualquer fatia dea
cria uma nova lista. Para clonar uma lista basta tomarmos a fatia como sendo a lista toda.
1 a = [81, 82, 83] 2 3 b = a[:] # cria um clone com fatia 4 print(a == b) 5 print(a is b) 6 7 b[0] = 5 8 9 print(a) 10 print(b) line that has just executednext line to executeProgram output:
FramesObjectsb
sem nos preocuparmos coma
. Note também que oid
de b é diferente doid
de a. Ela é uma lista completamente diferente.
Repetições e referências
Já vimos que o operador de repetição trabalho sobre strings e também sobre listas. Por exemplo.
1
2
3
4
lista_original = [45, 76, 34, 55]
print(lista_original*3)
Considere a seguinte extensão do exemplo anterior.
1
2
3
4
5
6
7
8
lista_original = [45, 76, 34, 55]
print(lista_original*3)
lista_nova = [lista_original] * 3
print(lista_nova)
lista_nova
é uma lista com três referências para alista_original
que foram criadas pelo operador de repetição.
Agora, o que acontece se modificamos um valor dalista_original
?
1
2
3
4
5
6
7
8
9
10
11
lista_original = [45, 76, 34, 55]
lista_nova = [lista_original] * 3
print(lista_nova)
lista_original[1] = 99
print(lista_nova)
lista_nova
mostra a mudança em três lugares. Isto pode ser facilmente entendido através do diagrama de referências, já que existe apenas umalista_original
. Logo, qualquer alteração nalista_original
aparece em cada uma das três referências danova_lista
.
Aqui está o mesmo exemplo no codelens. Execute o código passo a passo e preste particular atenção à execução do comando de atribuiçãolista_original[1] = 99
.
1 lista_original = [45, 76, 34, 55] 2 3 lista_nova = [lista_original] * 3 4 5 print(lista_nova) 6 7 lista_original[1] = 99 8 9 print(lista_nova) line that has just executednext line to executeProgram output:
FramesObjects
9.12.1: O que é impresso pelo trecho de código a seguir?
lista_a = [4, 2, 8, 6, 5] lista_b = lista_a * 2 lista_b[3] = 999 print(lista_a)
9.12.2: O que é impresso pelo trecho de código a seguir?
lista_a = [4, 2, 8, 6, 5] lista_b = [lista_a] * 2 lista_a[3] = 999 print(lista_b)
Métodos de listas
O operador ponto também pode ser usado para acessar métodos nativos (built-in) de objetos que são listas.append
é um método de listas que insere o argumento passado para ele no final da lista. O exemplo a seguir mostra vários outros métodos. Alguns deles são muito fáceis de serem compreendidos.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
minha_lista = []
minha_lista.append(5)
minha_lista.append(27)
minha_lista.append(3)
minha_lista.append(12)
print(minha_lista)
minha_lista.insert(1, 12)
print(minha_lista)
print(minha_lista.count(12))
print(minha_lista.index(3))
print(minha_lista.count(5))
minha_lista.reverse()
print(minha_lista)
minha_lista.sort()
print(minha_lista)
minha_lista.remove(5)
print(minha_lista)
ultimo_item = minha_lista.pop()
print(ultimo_item)
print(minha_lista)
pop
. A primeira, sem parâmetros, remove e retorna o último item da lista. Se for dado um argumento para a posição,pop
remove e retorna o item da posição. De qualquer maneira a lista é alterada.
A tabela a seguir mostra um resumo dos métodos de listas mostrados acima. Faça testes com esses métodos para ganhar uma melhor compreensão do que eles fazem.
Método Parâmetros Resultado Descrição append item mutador Acrescenta um novo item no final da lista insert posição, item mutador Insere um novo item na posição dada pop nenhum híbrido Remove e returno o último item pop posição híbrido Remove e retorna o item da posição. sort nenhum mutador Ordena a lista reverse nenhum mutador Ordena a lista em ordem reversa index item retorna idx Retorna a posição da primeira ocorrência do item count item retorna ct Retorna o número de ocorrências do item remove item mutador Remove a primeira ocorrência do item
É importante notar queappend
,sort
, ereverse
retornamNone
. Isto significa que atribuira aminha_lista
o resultado da ordenação deminha_lista
resultará na perda da lista.
1
2
3
4
5
6
7
8
9
10
11
minha_lista = []
minha_lista.append(5)
minha_lista.append(27)
minha_lista.append(3)
minha_lista.append(12)
print(minha_lista)
minha_lista = minha_lista.sort() # possivel erro
print(minha_lista)
9.13.1:
9.13.2: O que é impresso pelo trecho de código a seguir?
uma_lista = [4, 2, 8, 6, 5] uma_lista.insert(2,True) uma_lista.insert(0,False) print(uma_lista)
9.13.3:
9.13.4:
Scratch Editor
Retorno a sistemas-L
Retornemos aos sistemas-L que foram introduzidos na capítulo anterior e trataremos de uma característica interessante que usa listas.
Suponha que temos a seguinte gramática:
X X --> F[-X]+X F --> FF
[sentido, x, y]
. A primeira posição da lista armazena a sentido, a segunda armazena a coordenada x e a terceira a coordenada y.
Agora, se criarmos uma lista vazia e cada vez que virmos um ‘[‘ usarmos a funçãoappend
para inserir no seu final a lista contendo[sentido, x, y]
teremos um históricos das posições em que a tartaruga esteve. A última posição salva estará sempre no final da lista. Quando encontrarmos um ‘]’ no string, usamos a funçãopop
para remover a última informação inserida na lista.
Modifiquemos nossa funçãodrawLsystem
para iniciarmos a implementação do comportamento descrito.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import turtle
def drawLsystem(aTurtle,instructions,angle,distance):
savedInfoList = []
for cmd in instructions:
if cmd == 'F':
aTurtle.forward(distance)
elif cmd == 'B':
aTurtle.backward(distance)
elif cmd == '+':
aTurtle.right(angle)
elif cmd == '-':
aTurtle.left(angle)
elif cmd == '[':
savedInfoList.append([aTurtle.heading(),aTurtle.xcor(),aTurtle.ycor()])
print(savedInfoList)
elif cmd == ']':
newInfo = savedInfoList.pop()
print(newInfo)
print(savedInfoList)
else:
print('Error:', cmd, 'is an unknown command')
t = turtle.Turtle()
inst = "FF[-F[-X]+X]+F[-X]+X"
drawLsystem(t,inst,60,20)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import turtle
def drawLsystem(aTurtle,instructions,angle,distance):
savedInfoList = []
for cmd in instructions:
if cmd == 'F':
aTurtle.forward(distance)
elif cmd == 'B':
aTurtle.backward(distance)
elif cmd == '+':
aTurtle.right(angle)
elif cmd == '-':
aTurtle.left(angle)
elif cmd == '[':
savedInfoList.append([aTurtle.heading(),aTurtle.xcor(),aTurtle.ycor()])
print(savedInfoList)
elif cmd == ']':
newInfo = savedInfoList.pop()
aTurtle.setheading(newInfo[0])
aTurtle.setposition(newInfo[1],newInfo[2])
else:
print('Error:', cmd, 'is an unknown command')
t = turtle.Turtle()
inst = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF[-FFFFFFFFFFFFFFFF[-FFFFFFFF[-FFFF[-FF[-F[-X]+X]+F[-X]+X]+FF[-F[-X]+X]+F[-X]+X]+FFFF[-FF[-F[-X]+X]+F[-X]+X]+FF[-F[-X]+X]+F[-X]+X]+FFFFFFFF[-FFFF[-FF[-F[-X]+X]+F[-X]+X]+FF[-F[-X]+X]+F[-X]+X]+FFFF[-FF[-F[-X]+X]+F[-X]+X]+FF[-F[-X]+X]+F[-X]+X]+FFFFFFFFFFFFFFFF[-FFFFFFFF[-FFFF[-FF[-F[-X]+X]+F[-X]+X]+FF[-F[-X]+X]+F[-X]+X]+FFFF[-FF[-F[-X]+X]+F[-X]+X]+FF[-F[-X]+X]+F[-X]+X]+FFFFFFFF[-FFFF[-FF[-F[-X]+X]+F[-X]+X]+FF[-F[-X]+X]+F[-X]+X]+FFFF[-FF[-F[-X]+X]+F[-X]+X]+FF[-F[-X]+X]+F[-X]+X"
t.setposition(0,-200)
t.left(90)
drawLsystem(t,inst,30,2)
inst
fornecido aqui, use o código do capítulo String, e escreve suas próprias funçãoapplyRules
para implementar o sistema-L. Este exemplo usa apenas 6 expansões. Teste com um número maior de expansões. Você também pode desejar executar com um exemplo com valores diferentes para o ângulo e a distância.
Scratch Editor
Append versus concatenação
O métodoappend
acrescenta um novo item no final da lista. É possível acrescentar um item no final da lista usando o operador+
de concatenação. Entretanto, precisamos ser cuidadosos.
Considere o exemplo a seguir. A lista original contém 3 inteiros. Nós inserimos a palavra “gato” no final da lista.
1 lista_orig = [45,32,88] 2 3 lista_orig.append("gato") line that has just executednext line to executeFramesObjectsappend
que simplesmente modifica a lista. A fim de concatenar necessitamos usar o comando de atribuição:
lista_orig = [45, 32, 88] lista_orig = lista_orig + ["gato"]
1 lista_orig = [45, 32, 88] 2 3 lista_orig = lista_orig + ["gato"] line that has just executednext line to executeFramesObjectsappend
, a lista original é simplemente modificada. É possível ver isto observando o id delista_orig
. O id é o mesmo antes e depois de executarmos append.
Por outro lado, com concatenação, você verá que o id da lista original não é o mesmo que o id da resultado depois do comando de atribuição. Execute um passo a passo cuidadoso de ambos os exemplos para notar a diferença. Com a concatenação um nova lista é criada.
Teste seu entendimento
9.15.1: O que é impresso pelo trecho de código a seguir?
uma_lista = [4, 2, 8, 6, 5] uma_lista = uma_lista + 999 print(uma_lista)
Listas e o laço
É possível percorrermos uma lista (list traversal) iterando através de itens ou iterando através de índices.for
1
2
3
4
5
6
frutas = ["pera", "laranja", "banana", "cereja"]
for uma_fruta in frutas: # por item
print(uma_fruta)
Podemos também usar o índice para acessar os itens iterativamente.
1
2
3
4
5
6
frutas = ["pera", "laranja", "banana", "cereja"]
for posicao in range(len(frutas)): # por índice
print(frutas[posicao])
posição
é usada como um índice da lista, imprimindo oposicao
-ésimo item. Note que usamoslen
como limite superior do intervalo de tal forma que podemos iterar corretamente independentemente do número de itens na lista.
Qualquer expressão sequencial pode ser usada em um laçofor
. Por exemplo, a funçãorange
retornal uma sequência de inteiros.
1
2
3
4
5
for numero in range(21):
if numero % 3 == 0:
print(numero)
Como listas são mutáveis, é frequentemente desejável que modifiquemos os elementos de uma lista a medida que ela é percorrida. No código a seguir todos os números inteiros entre1
e5
são elevados ao quadrado utilizando iteração por posição.
1
2
3
4
5
6
7
8
9
numeros = [1, 2, 3, 4, 5]
print(numeros)
for i in range(len(numeros)):
numeros[i] = numeros[i]**2
print(numeros)
range(len(numeros)
até que você entenda como funciona. Estamos interessados aqui sobre ambos o valor e o índice de uma posição da lista de tal maneira que atribuir un novo valor à posição.
Scratch Editor
9.16.1: O que é impresso pelo trecho de código a seguir?
lista = [4, 2, 8, 6, 5] nova_lista = [ ] for item in lista: nova_lista.append(item+5) print(nova_lista)
Listas como parâmetros
Funções que recebem listas como argumentos e as alteram durante a execução são chamadas de modificadoras (modifiers) e as mudanças elas realizam são chamadas efeitos colaterais (side effects). Ao passar uma lista como argumento estamos realmente passando para a função uma referência para a lista e não um cópia (clone) da lista. Como listas são mutáveis as alterações feitas nos elementos referenciados pelos parâmetros mudarão a lista que o argumento está referenciando. Por exemplo, a função a seguir recebe uma lista como argumento e multiplica cada elemento da lista por 2:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def double_stuff(lista):
""" (list) -> None
Recebe uma lista referenciada por
'lista' e sobreescreve cada
elemento da lista com o dobro do
seu valor.
"""
for posicao in range(len(lista)):
lista[posicao] = 2 * lista[posicao]
things = [2, 5, 9]
print(things)
double_stuff(things)
print(things)
lista
e a variável (argumento)things
são apelidos para o mesmo objeto.
Como a lista de objetos é compartilhada por duas referências, existe apenas uma cópia. Se a função modifica os elementos da lista parâmetros, o função que fez a chamada também enxerga as alterações, já que as alterações estão ocorrendo no original.
This can be easily seen in codelens. Note that after the call todouble_stuff
, the id of the formal parameteruma_lista
is the same as the id ofthings
.
1 def double_stuff(lista): 2 """ (list) -> None 3 Recebe uma lista referenciada por 4 'lista' e sobreescreve cada elemento 5 da lista com o dobro do seu valor. 6 """ 7 for posicao in range(len(lista)): 8 lista[posicao] = 2 * lista[posicao] 9 10 things = [2, 5, 9] 11 12 double_stuff(things) line that has just executednext line to executeFramesObjectsFunção pura
Uma função pura (pure function) não produz efeito colateral. Sua comunicação com a função que a chamou é somente através do parâmetros, que não são modificados e um valor é retornado. Aqui está um versão pura da funçãodouble_stuff
da seção anterior. Para usar versão pura dedouble_stuff
e modificarthings
, devemos atribuir o valor retornado athings
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def double_stuff(lista):
""" (list) -> list
Recebe uma lista referenciada por
'lista' e cria e retorna uma nova
lista em que cada elemento e' o
dobro do valor correspondente
na lista original.
"""
nova_lista = []
for valor in lista:
novo_elemento = 2 * valor
nova_lista.append(novo_elemento)
return nova_lista
things = [2, 5, 9]
print(things)
things = double_stuff(things)
print(things)
1 def double_stuff(lista): 2 """ (list) -> list 3 Recebe uma lista referenciada por 4 'lista' e cria e retorna uma nova 5 lista em que cada elemento e' o 6 dobro do valor correspondente 7 na lista original. 8 """ 9 nova_lista = [] 10 for valor in lista: 11 novo_elemento = 2 * valor 12 nova_lista.append(novo_elemento) 13 return nova_lista 14 15 things = [2, 5, 9] 16 things = double_stuff(things) line that has just executednext line to executeFramesObjectsScratch Editor
Qual é melhor?
Tudo que é feito com uma função modificadora pode também ser realizado com uma função pura. De fato, algumas linguagens de programação somente permitem funções puras. Existe alguma evidência que programas que usam funções puras são desenvolvidos mais rapidamente e propagam menos erros que programas que usam funções modificadoras. No entanto, modificadoras são as vezes convenientes e em alguns casos, programas funcionais não menos eficientes.
Em geral, recomendamos que você escreva funções puras sempre que for razoável fazer isso é apele para modificadoras somente se existe uma boa vantagem em fazer isso. Este método pode ser chamado de estilo funcional de programação (functional programming style).
Funções que produzem listas
A versão pura da funçãodouble_stuff
acima faz uso de um padrão (pattern) que você deve guardar na sua caixa de ferramentas. Sempre que você necessitar escrever uma função que cria e retorna uma lista, o padrão usualmente é:
inicialize uma variável para a lista nova com a lista vazia itere crie um novo elemento append esse novo elemento a lista nova retorne a lista nova
primo(x)
que recebe um número inteirox
e retornaTrue
se o valor dex
é primo eFalse
em caso contrário. Agora, escrevemos uma função que recebe um número inteiron
e cria e retorna uma lista com todos os números primos menores quen
:
def primos_ate(n): """ (int) -> list Recebe um inteiro n e cria e retorna a lista dos números primos menores que n. """ lista_primos = [] for i in range(2,n): if primo(i): lista_primos.append(i); return lista_primos
List comprehensions
No exemplo anterior criamos uma lista de uma sequência de valores (os inteiros entre 2 en
) baseados em um critério de seleção (ser primo). Um maneira simples para realizar em Python esse tipo de processamento é o uso de list comprehension. (N.d.T. também traduzido para o português como abrangência de listas. Ver o comentário em: List comprehensions ou abrangências de listas.)
List comprehension é uma maneira compacta de criar listas. A forma geral para obter esse efeito é:
[<expressão> for <item> in <sequência> if <condição>]
if
é opcional. Por exemplo,
1
2
3
4
5
6
7
minha_lista = [1, 2, 3, 4, 5]
sua_lista = [item ** 2 for item in minha_lista]
print(sua_lista)
for
itera sobre cada elemento da sequencia. Os itens são filtrados pela cláusulaif
se existe alguma. No exemplo acima, o comandofor``faz com que a variável ``item
assuma todos os valores na listaminha_lista
. Cada item é elevado ao quadrado antes de ser inserido na lista que está sendo construída. O resultados é a lista dos quadrados dos valores emminha_lista
.
Para escrever a funçãoprimos_ate
usaremos a funçãoprimos
como um filtro dos inteiros na sequência resultante derange
. Em outras palavras, para cada inteiro de 2 atén
, exclusiven
, se o inteiro é primo, ele será mantido na lista resultante.
def primes_ate(n): """ (int) -> list Recebe um inteiro n e cria e retorna a lista dos números primos menores que n usando 'list comprehension'. """ lista_primos = [num for num in range(2,n) if primo(num)] return lista_primos
Scratch Editor
9.20.1: O que é impresso pelo trecho de código a seguir?
uma_lista = [4,2,8,6,5] outra_lista = [num*2 for num in uma_lista if num%2==1] print(outra_lista)
Listas aninhadas
Uma lista aninhada (nested list) é uma lista que aparece como um elemento em uma outra lista. Nessa lista, o elemento com índice 3 é uma lista aninhada. Se executarmos print(lista[3]
), obteremos[10, 20]
. Para acessar um elemento de uma lista aninhada podemos proceder em dois passos. Primeiro, acessamos a lista aninhada, depois acessamos o item de interesse. Também é possível combinar esses passos usando o operador colchetes que são aplicados da esquerda para a direita.
1
2
3
4
5
6
7
8
9
lista = ["oi", 2.0, 5, [10, 20]]
lista_aninhada = lista[3]
print(lista_aninhada)
item = lista_aninhada[1]
print(item)
print(lista[3][1])
Teste seu entendimento9.21.1: O que é impresso pelo trecho de código a seguir?
lista = [ [4, [True, False], 6, 8], [888, 999] ] if lista[0][1][0]: print(lista[1][0]) else: print(lista[1][1])
Strings e listas
Dois dos métodos mais úteis que operam sobre strings envolvem listas de strings. O métodosplit
quebra um string em uma lista de palavras. Por palavra entenda-se um string limitado por um conjunto de caracteres pré-definidos. Em caso de omissão (default), qualquer número de caracteres brancos (whitespace characters) é considerado como limite de uma palavra.
1
2
3
4
5
musica = "Eduardo e Monica um dia se encontraram sem querer..."
lista_palavras = musica.split()
print(lista_palavras)
1
2
3
4
5
musica = "Eduardo e Monica um dia se encontraram sem querer..."
lista_palavras = musica.split("se")
print(lista_palavras)
O métodojoin
faz o trabalho inverso do métodosplit
. Determinamos um string separador (separator), frequentemente chamado de cola (glue) e juntamos os elementos na lista utilizando a cola entre cada par de elemento.
1
2
3
4
5
6
7
8
9
10
lista = ["vermelho", "azul", "verde"]
cola = ';'
s = cola.join(lista)
print(s)
print(lista)
print("***".join(lista))
print("".join(lista))
lista
no exemplo) não é modificada. É possível utilizar qualquer string como cola, inclusive o string vazio.
Scratch Editor
9.22.1: O que é impresso pelo trecho de código a seguir?
escritora = "Carolina Maria de Jesus" lista_de_nomes = escritora.split() inic = "" for nome in lista_de_nomes: inic = inic + nome[0] print(inic)
Função de conversão
Python possui uma função nativa chamadalist
list
que procura converter o seu argumento para o tipo list.
1
2
3
4
xs = list("Crunchy Frog")
print(xs)
list
sobre qualquer argumento que não seja uma sequência.
É importante observar que a função de conversãolist
colocará cada elemento da sequência original em uma nova lista. Quando estamos trabalhando com strings isto é muito diferente do resultado do métodosplit
. Enquanto quesplit
quebra uma string em um lista de “palavras”,list
sempre quebra o string em uma lista de caracteres.
Tuplas e mutabilidade
Até agora vimos dois tipos de coleções sequenciais de objetos: strings, que são compostos de caracteres; e listas. que são formados por elementos de um qualquer tipo. Uma das diferenças que notados é que os elementos de uma lista podem ser modificados, mas os caracteres de um string não podem. Em outras palavras, strings são imutáveis (immutable) e listas são mutáveis (mutable).
Uma tupla (tuple), como uma lista, é um sequência de items de qualquer tipo. Entretanto, diferentemente de listas, tuples são imutáveis. Sintaticamente, uma tupla é uma sequência de valores separadas por uma vírgula. Apesar de não ser necessário, há a convenção de se envolver uma tupla entre parêntese:
fernanda = ("Fernanda", "Montenegro", 1929, "Central do Brasil", 1998, "Atriz", "Rio de Janeiro, RJ")
Tuplas admitem a mesma sequência de operações que strings e listas. Por exemplo, com o operador de indexação selecionamos um elemento de uma tupla.
Como strings, se tentarmos utilizar o operador de atribuição para modificarmos um elemento da tupla, obteremos um erro.
fernanda[0] = 'X' TypeError: 'tuple' object does not support item assignment
fernanda
tem um filme mais recente e nós podemos desejar alterar a sua tupla. Podemos facilmente usar fatiar as partes da tupla original que desejamos concatenar a fim de obtermos uma nova tupla.
1
2
3
4
5
6
7
8
9
10
fernanda = ("Fernanda", "Montenegro", 1929, "Central do Brasil", 1998, "Atriz", "Rio de Janeiro, RJ")
print(fernanda[2])
print(fernanda[2:6])
print(len(fernanda))
fernanda = fernanda[:3] + ("Boa Sorte", 2014) + fernanda[5:]
print(fernanda)
(5)
abaixo como um número inteiro entre parenteses:
1
2
3
4
5
6
7
tup = (5,)
print(type(tup))
x = (5)
print(type(x))
Atribuição de tuplas
Python tem um mecanismo muito poderoso de atribuição de tuplas (tuple assignment) que permite uma tupla de variáveis na esquerda receber valore de uma tupla de variáveis a direita do operador=
de atribuição.
(nome, sobrenome, ano_de_nascimento, filme, ano_do_filme, profissao, local_de_nascimento) = fernanda
Frequentemente, é útil trocarmos os valores de duas variáveis. Com o comando de atribuição convencional necessitamos de uma variável temporária. Por exemplo, para trocar os valores dea
eb
:
temp = a a = b b = temp
(a, b) = (b, a)
>>> (a, b, c, d) = (1, 2, 3) ValueError: need more than 3 values to unpack
Tuplas como valor de retorno
Funções podem retornar tuplas como valor de retorno. Isto é muito conveniente — frequentemente desejamos saber qual foi o maior número de gols marcados e o maior número de gols sofridos por um time, ou desejamos o média e desvio padrão de um conjunto de dados, ou sejamos saber um dia, mês e ano ou se estamos fazendo alguma modelagem ecológica desejamos saber o número de coelho e lobos em uma ilha em um certo momento. Em cada um desses casos, uma função (que só pode retornar um único valor), pode cria uma tupla formada por vários valores.
Por exemplo, podemos escrever uma função que retorna a área de um círculo e comprimento de uma circunferência de um dado raio.
1
2
3
4
5
6
7
8
9
10
11
12
def circInfo(r):
""" (numero) -> (float,float)
Recebe um numero r e retorna o comprimento da circunferencia
de raio r e a area do circulo de raio r.
"""
c = 2 * 3.14159 * r
a = 3.14159 * r * r
return (c, a)
print(circInfo(10))
Scratch Editor
Glossário
- apelidos (aliases)
- Várias variáveis fazendo referência a um mesmo objeto.
- clonar (clone)
- Criar um novo objeto com os mesmo valores de um objeto existente. Copiar uma referência de um objeto cria um apelido mas não cria um clone do objeto.
- delimitador (delimiter)
- Um caractere ou string usado para indicar onde um string deve ser “quebrado”.
- efeito colateral (side effect)
- Um mudança no estado de um programa feito por uma função que foi invocada que não é o resultado do valor retornado pela função. Efeitos colaterais só podem ser produzidos por função midificadoras.
- elemento
- Um dos valores em uma lista (ou outra sequência). O operador colchetes seleciona elementos de uma lista.
- função pura (pure functon)
- Uma função que não produz efeitos colaterais. Funções puras apenas alteram os estado (variáveis) das funções que a chamam através de valores de retorno.
- índice (index)
- Uma variável, valor ou expressão do tipo
int
que indica um elemento de uma lista, string ou tupla. - lista (list)
- Uma coleção de objetos, onde cada objeto é identificado por um índice.
Como outros tipos
str
,int
,float
, etc. existe também a funçãolist
que procura converter o seu argumento para uma lista. - lista aninhada (nested list)
- Uma lista que é um elemento de uma outra lista.
- modificadora (modifier)
- Uma função que altera os seus argumntos. Somente argumentos de tipos mutáveis podem ser alterados por funções modificadoras.
- objeto (object)
- Um valor a que uma variável pode se referir.
- percorrer um lista (list traversal)
- Acesso sequencial a cada elemneto em uma lista.
- padrão (pattern)
- Uma sequência de comandos ou um estilo de escrever código que é potencialmente aplicável em várias situações. Parte de se tornar um cientista da computação madura está em aprender e estabelecer padrões e algoritmos que formam a sua caixa de ferramentas. Padrões frequentemente correspondem ao seu “mental chunking”.
- sequência (sequence)
- Qualquer tipo de dados que consiste de uma coleção ordenada de elementos, com cada elemento identificado por um índice.
- tipo de dado mutável (mutable data type)
- Um tipo de dado em que seu elementos podem ser modificados. Todos os tipos mutáveis são compostos por outros tipos. Listas são mutáveis; strings e tuplas não são mutáveis.
Exercícios
- Desenhe um diagrama de referências para
a
eb
antes e depois de ser executada a terceira linha do seguinte trecho de código:a = [1, 2, 3] b = a[:] b[0] = 5
- Cria uma lista chamada
minha_lista
com os seguinte items: 76, 92.3, “oi”, True, 4, 76.
-
- Escreva comandos para:
- Inserir “pera” e 76 no final da lista.
- Inserir o valor “gato” na posição de índice 3.
- Inserir o valor 99 no início da lista.
- Encontrar o índice de “oi”.
- Contar o número de ocorrências de 76 na lista.
- Remover a primeira ocorrência de 76 da lista.
- Remover True True da lista usando
pop
eindex
.
-
- Crie uma lista contendo 100 números inteiros aleatórios entre 0 e 1000 (usando iteração, ´´append´´ e o módulo random). Escreva uma função
media
que recebe uma lista de números como parâmetros e retorna a média dos valores na lista. -
- Escreva uma função que recebe a lista de inteiros do exercício anterior e retorna o maior valor na lista. (Observação: existe uma a função nativa
max
que faz o serviço, mas você não deve usá-la.) -
- Escreva uma função
soma_de_quadrados(xs)
que recebe uma lista de números xs e retorna a soma dos quadrados dos números na lista. Por exemplosoma_dos_quadrados([2, 3, 4])
deve retorna 4+9+16 que é 29. -
- Escreva uma função que recebe uma lista de números inteiros e retorna a quantida de números ímpares na lista.
-
- Escreva uma função que recebe uma lista de números inteiros e retorna a soma dos números pares na lista.
-
- Escreva uma função que recebe uma lista de números e retorna a soma dos números negativos na lista.
-
- Escreva uma função que recebe uma lista de palavras (strings) e retorna o número de palavras na lista que tem comprimento 5.
-
- Escreva uma função que recebe uma lista de números inteiros e retorna a soma dos números na lista exclusive o primeiro número par.
-
- Escreva uma função que recebe uma lista de palavras (strings) e retorna o número de palavras que ocorre na lista até e inclusive a primeira ocorrência da palavra “sam”.
-
- Apesar de Python nós fornecer uma grande lista de métodos nativos é uma boa prática e instrutivo pensar sobre como elas podem ser implementadas. Implemente uma função que se comporte como:
- count
- in
- reverse
- index
- insert
- Escreva uma função
troca(s, velho, novo)
que recebe os stringss
,velho
enovo
e troca ems
todas as ocorrências develho
pornovo
:test(troca('Mississippi', 'i', 'I'), 'MIssIssIppI') s = 'I love spom! Spom is my favorite food. Spom, spom, spom, yum!' test(troca(s, 'om', 'am'), 'I love spam! Spam is my favorite food. Spam, spam, spam, yum!') test(troca(s, 'o', 'a'), 'I lave spam! Spam is my favarite faad. Spam, spam, spam, yum!')
split
ejoin
.
-
- Aqui estão as regras para um sistema-L que cria algo que lembra um jardim comum de evas. Implemente as regras a seguir e teste-as. Use o ângulo de 25.7 graus.:
H H --> HFX[+H][-H] X --> X[-FFF][+FFF]FX
-
- Aqui está outro sistema-L. Use o ângulo de 25 graus:
F F --> F[-F]F[+F]F
No hay comentarios:
Publicar un comentario