Conteúdo 1 Listas em compreensão

Propaganda
Nesta aula. . .
Conteúdo
1
Listas em compreensão
1
2
Exemplo: obfuscar um texto
3
1
Listas em compreensão
Processamento de listas
Duas operações comuns:
• selecionar elementos que verificam uma condição
• calcular uma expressão para cada elemento
Calcular quadrados
Usando um ciclo para construir a lista dos quadrados:
def quadrados(xs):
"Calcula o quadrados de cada elemento de xs."
ys = []
for x in xs:
ys = ys+[x**2]
return ys
>>> quadrados(range(10))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Listas em compreensão
Calculando os quadrados usando uma expressão em compreensão:
>>> [x**2 for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Notação inspirada na teoria de conjuntos:
{x2 : x ∈ {0, 1, . . . , 9}}
1
Sintaxe
[expressão for variável in sequência]
>>> [x**2 for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> [(c,ord(c)) for c in "pedro"]
[(’p’, 112), (’e’, 101), (’d’, 100),
(’r’, 114), (’o’, 111)]
Listas em compreensão com condições
[expr for variável in sequência if condição]
Exemplo: quadrados dos múltiplos de 3 menores que 10.
>>> [x**2 for x in range(10) if x%3==0]
[0, 9, 36, 81]
Listas em compreensão embricadas
Podemos usar uma expressão em compreensão dentro de outra.
Por exemplo, a matriz identidade de 4 × 4:
>>> [[int(i==j) for j in range(4)]
for i in range(4)]
[[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]]
Compreensões com múltiplas sequências
Análogo ao producto cartesiano de dois conjuntos:
>>> [(x,y)
[(’A’, 0),
(’B’, 0),
(’C’, 0),
for x
(’A’,
(’B’,
(’C’,
in "ABC" for y in range(4)]
1), (’A’, 2), (’A’, 3),
1), (’B’, 2), (’B’, 3),
1), (’C’, 2), (’C’, 3)]
A ordem do resultado depende da ordem das sequências:
>>> [(x,y)
[(’A’, 0),
(’B’, 1),
(’C’, 2),
for y
(’B’,
(’C’,
(’A’,
in range(4) for x in "ABC"]
0), (’C’, 0), (’A’, 1),
1), (’A’, 2), (’B’, 2),
3), (’B’, 3), (’C’, 3)]
2
Sintaxe geral
[expr for var1 in seq1 if cond1
for var2 in seq2 if cond2
.
.
.
for varN in seqN if condN ]
2
Exemplo: obfuscar um texto
Exemplo: obfuscar um texto
• um método para evitar que um texto electrónico seja lido inadvertidamente
• usando em grupos de discussão e forums para ocultar conteúdos (comentários
sobre jogos, filmes, livros, etc.)
• não é um segredo: qualquer pessoa pode descodificar o texto se quiser
ROT13: ROTate by 13 places
Cada letra é transformada noutra à distância de 13 posições:
13 letras
z
A
ROT13 l
N
B
l
O
C
l
P
D
l
Q
E
l
R
H
ROT13 ↓
U
F
l
S
}|
G H
l l
T U
I
l
V
E
↓
R
L
↓
Y
O
↓
B
L
↓
Y
J
l
W
K
l
X
L
l
Y
M
l
Z
{
Para descodificar basta aplicar ROT13 outra vez:
U
ROT13 ↓
H
R
↓
E
Y
↓
L
Y
↓
L
B
↓
O
Implementar ROT13
• uma função em Python rot13(txt) para transformar uma cadeia de caracteres txt usando ROT13
• espaços, algarismos e símbolos de pontuação ficam inalterados
• letras maiúsculas e minúsculas devem ser transformadas
3
Ideia
• uma função auxiliar rot13char para transformar apenas um caracter
• aplicamos rot13char a todos os caracteres de txt
• vamos usar expressões em compreensão
Transformar um caracter
def rot13char(c):
"Transforma um caracter por rotação 13."
# será letra maiúscula ou mínuscula?
if (c>=’a’ and c<=’m’) or (c>=’A’ and c<=’M’):
return chr(ord(c) + 13)
elif (c>=’n’ and c<=’z’) or (c>=’N’ and c<=’Z’):
return chr(ord(c) - 13)
else:
return c # outros símbolos: inalterados
Transformar uma cadeia (1a tentativa)
def rot13(txt):
"Transforma txt por rotaçao 13."
return [rot13char(c) for c in txt]
>>> rot13(’HELLO’)
[’U’, ’R’, ’Y’, ’Y’, ’B’]
>>> rot13(’Ola, mundo!’)
[’B’, ’y’, ’n’, ’,’, ’ ’, ’z’, ’h’, ’a’,
’q’, ’b’, ’!’]
O resultado é uma lista em vez de uma cadeia de caracteres.
Precisamos de uma função para concatenar uma lista de cadeias. . .
Transformar uma cadeia (corrigido)
def concat(lista):
"Concatena uma lista de cadeias."
conc = ””
# resultado da concatenação
for txt in lista:
conc = conc+txt
return conc
def rot13(txt):
"Transforma txt por rotaçao 13."
return concat([rot13char(c) for c in txt])
4
Exemplos
>>> rot13("Python e’ uma linguagem poderosa!")
"Clguba r’ hzn yvathntrz cbqrebfn!"
>>> rot13("Clguba r’ hzn yvathntrz cbqrebfn!")
"Python e’ uma linguagem poderosa!"
Variante
• quero tornar o texto ainda mais obfuscado!
• os sinais de pontuação e espaços dão indicação sobre onde começam e acabam
as palavras
• vamos modificar a função para remover todos os caracteres excepto as letras
• podemos fazer isso usando uma condição na expressão de compreensão
Modificação para remover não-letras
import string
def rot13(txt):
"Transforma txt por rotaçao 13."
return concat([rot13char(c) for c in txt
if c in string.letters])
# string.letters == ’abcdef... ABCDEF...’
O resto do programa fica inalterado!
Execução
>>> rot13("Python e’ uma linguagem poderosa!")
"Clgubarhznyvathntrzcbqrebfn"
>>> rot13("Clgubarhznyvathntrzcbqrebfn")
"Pythoneumalinguagempoderosa"
Não obtemos exactamente o texto orignal, mas ainda é compreensível. . .
5
Sumário
• expressões em compreensão são uma notação sucinta para dois tipos comuns de
processamento de listas:
1. selecionar elementos por uma condição
2. calcular uma expressão para cada elemento
• é possível fazer as mesmas operações apenas com ciclos
• as expressões em compreensão são mais sucintas e simples
• apenas algumas linguagens de programação permitem expressões em compreensão: Haskell, Python, Perl 6, C# 3.0, F#. . .
6
Download