Listas avançadas
Laço for
em índices de listas
Laços for
normalmente percorrem os valores em uma lista (os elementos):
for elemento in lista:
## elemento variável no processo
Podemos, alternativamente, percorrer os índices da lista:
for i in range(0, len(lista), 1):
elemento = lista[i]
## processa o elemento ou lista[i] diretamente
range(start, stop, inc)
gera uma lista de inteiros iniciando pelo valor de start
, depois start + inc
, depois start + 2*inc
e assim por diante até um valor antes do valor de stop
.
range(stop)
é um código curto para range(0, stop, 1)
.
>>> range(3) ## = range(0, 3, 1)
[0, 1, 2]
>>> range(2, 8, 3)
[2, 5]
Como podemos mudar elementos em uma lista?
Digamos que queremos adicionar o número 2 a todos os números em uma lista:
>>> v = [-1, 1, 10]
>>> for e in v:
... e = e + 2
...
>>> v
[-1, 1, 10] ## não alterado!!
Mas o e
não é um elemento da lista?!?
É preciso um elemento indexado
Mudar um elemento de uma lista requer a atribuição à um elemento indexado.
Qual é o problema?
Dentro do laço, e
é uma simples variável (tipo int
), no primeiro passo se torna 1, depois 3, depois 12, mas a lista v
é inalterada.
Solução: é necessário indexar um elemento de uma lista para mudar o seu valor:
>>> v = [-1, 1, 10]
>>> v[1] = 4 ## atribui 4 para o 2o elemento (índice 1) em v
>>> v
[-1, 4, 10]
>>>
>>> for i in range(len(v)):
... v[i] = v[i] + 2
...
>>> v
[1, 6, 12]
Compreensão da lista
Como criar listas de maneiras compactas?
Exemplo: compute duas listas em um laço for
.
n = 16
Cgraus = []; Fgraus = [] ## listas vazias
for i in range(n):
Cgraus.append(-5 + i*0.5)
Fgraus.append((9.0/5)*Cgraus[i] + 32)
Python possui um construtor compacto chamado compreensão da lista, list comprehension, para a geração de listas a partir de um laço for
:
Cgraus = [-5 + i*0.5 for i in range(n)]
Fgraus = [(9.0/5)*C + 32 for C in Cgraus]
Forma geral de uma compreensão da lista, list comprehension:
lista = [expressão for elemento in lista]
Sendo que a expressão
envolve o elemento
Demonstração interativa da compreensão da lista
Atravessando múltiplas listas
Podemos correr um laço sobre duas listas?
Solução 1: laço sobre índices
for i in range(len(Cgraus)):
print Cgraus[i], Fgraus[i]
Solução 2: usar o construtor zip
:
for C, F in zip(Cgraus, Fgraus):
print C, F
Exemplo com três listas:
>>> l1 = [3, 6, 1]; l2 = [1.5, 1, 0]; l3 = [9.1, 3, 2]
>>> for e1, e2, e3 in zip(l1, l2, l3):
... print e1, e2, e3
...
3 1.5 9.1
6 1 3
1 0 2
Listas de listas
- Uma lista pode conter qualquer objeto, inclusive outra lista.
- Ao invés de se armazenar uma tabela com duas listas separadas, uma para cada coluna, podemos agrupar as duas listas em uma nova:
Cgraus = range(-20, 41, 5)
Fgraus = [(9.0/5)*C + 32 for C in Cgraus]
tabela1 = [Cgraus, Fgraus] ## lista de duas listas
print tabela1[0] ## a lista Cgraus
print tabela1[1] ## a lista Fgraus
print tabela1[1][2] ## o 3o elemento em Fgraus
Tabela de colunas X tabela de linhas
- A tabela anterior
table = [Cgraus,Fgraus]
é uma tabela de duas colunas. - Vamos fazer uma tabela de linhas, onde cada linha é um par $C, F$:
tabela2 = []
for C, F in zip(Cgraus, Fgraus):
linha = [C, F]
tabela2.append(linha)
## mais compacto com a compreensão de lista:
tabela2 = [[C, F] for C, F in zip(Cgraus, Fgraus)]
print tabela2
[[-20, -4.0], [-15, 5.0], ......., [40, 104.0]]
Iteração sobre a lista de listas:
for C, F in tabela2:
## funciona com C e F de uma linha na tabela2
## ou
for linha in tabela2:
C, F = linha
...
Ilustração da tabela de colunas
Ilustração da tabela de linhas
Extraindo sublistas
Podemos facilmente pegar partes de uma lista:
>>> A = [2, 3.5, 8, 10]
>>> A[2:] ## do índice 2 ao final da lista
[8, 10]
>>> A[1:3] ## do índice 1 até o índice anterior ao índice 3
[3.5, 8]
>>> A[:3] ## do início até o índice anterior ao índice 3
[2, 3.5, 8]
>>> A[1:-1] ## do índice 1 até o elemento final
[3.5, 8]
>>> A[:] ## a lista toda
[2, 3.5, 8, 10]
Nota: sublistas (fatias) são cópias da lista original!
Cópias e Visualizações
Um simples objeto pode ter diversos nomes conectados a ele, execute os códigos abaixo e preste atenção no resultado:
a = [1, 2, 3]
b = a
a
b
a is b
b[1] = 'oi!'
a
b
é uma visualização de a
, então se b
muda, a
também muda.
O conceito chave aqui é mutável x imutável:
- Objetos mutáveis podem ser modificados;
- Objetos imutáveis não podem mais ser modificados após serem criados.
O que esse pedaço de código faz?
for C, F in tabela2[Cgraus.index(10):Cgraus.index(35)]:
print '%5.0f %5.1f' % (C, F)
- É um laço
for
sobre uma sublista da tabela2. - Índices de sublistas:
Cgraus.index(10)
,Cgraus.index(35)
, ou seja, os índices que correspondem aos elementos 10 e 35.
Saída:
10 50.0
15 59.0
20 68.0
25 77.0
30 86.0
Iteração sobre listas de listas de listas...
No caso de listas com muitos índices, como por exemplo: lista[i1][i1][i3]...
Laços sobre os índices da lista seriam:
for i1 in range(len(lista)):
for i2 in range(len(lista[i1])):
for i3 in range(len(lista[i1][i2])):
for i4 in range(len(lista[i1][i2][i3])):
valor = lista[i1][i2][i3][i4]
## trbalhando a variável valor
Laços sobre sublistas:
for sublista1 in lista:
for sublista2 in lista1:
for sublista3 in lista2:
for sublista4 in lista3:
valor = lista4
## trbalhando a variável valor
Iteração sobre uma lista de listas específica
Como podemos indexar o elemento de valor 5?
Funcionalidades de listas
Construção | Significado |
---|---|
a = [] |
inicializa uma lista vazia |
a = [1, 4.4, 'run.py'] |
inicializa a lista |
a.append(elem) |
adiciona o objeto elem ao final |
a + [1,3] |
adiciona duas listas |
a.insert(i, e) |
insere o elemento e antes do índice i |
a[3] |
elemento da lista na posição 3 |
a[-1] |
pega o último elemento da lista |
a[1:3] |
corte: copia dos dados para uma sublist (aqui: índices 1, 2) |
del a[3] |
apaga um elemento (índice 3 ) |
a.remove(e) |
remove um elemento com o valor e |
a.index('run.py') |
busca o índice correspondente ao valor do elemento |
'run.py' in a |
testa se um valor está na lista |
a.count(v) |
conta quantos elementos possuem o valor v |
len(a) |
número dos elementos na lista a |
min(a) |
o menor elemento na lista a |
max(a) |
o maior elemento na lista a |
sum(a) |
soma todos os elementos de a |
sorted(a) |
retorna uma versão ordenada da lista a |
reversed(a) |
retorna uma versão ordenada ao inverso da lista a |
b[3][0][2] |
indexação de listas de listas |
isinstance(a, list) |
é True se a é uma lista |
type(a) is list |
é True se a é uma lista |