Contents

Fundamentos de Matemática Discreta com Python

Matemática Discreta

A matemática é uma ciência fundamental para qualquer formação ligada à computação, à informática e, em nosso caso, à ciência e análise de dados. Porém, a característica distintiva da matemática realizada pelas máquinas é a finitude. Isto é, enquanto a matemática tradicional que aprendemos é capaz de lidar com quantidades infinitas e incontáveis, as máquinas possuem limitações em suas capacidades, seja em armazenamento, seja em memória. Embora tais capacidades sejam expansíveis de alguma forma, devemos compreender que os recursos computacionais são finitos.

Chamamos de Matemática Discreta (ou Álgebra Abstrata) a área da Matemática que lida com objetos discretos, a saber, conjuntos, sequencias, listas, coleções ou quaisquer entidades contáveis. Por exemplo, diz-se que o conjunto dos números reais é incontável, ou não enumerável, pelo fato de não conseguirmos obter um paralelo entre seus elementos e o conjunto dos números naturais. Em outras palavras, não podemos determinar o número de elementos do conjunto R. Por outro lado, isto não acontece com uma variedade de outros conjuntos que podemos encontrar na vida real. Observemos os exemplos:

  • O conjunto das vogais da língua portuguesa;

  • O conjunto dos times de futebol brasileiros da série A em 2020;

  • O conjunto de nomes das estações do ano;

  • O conjunto das personagens que formam o quarteto principal do filme Os Pinguins de Madagascar e;

  • O conjunto dos números pares positivos menores ou iguais a dez.

Cada conjunto desses possui um número finito de elementos. Isto quer dizer que são contáveis, ou enumeráveis. Podemos defini-los, em linguagem matemática, por meio da extensão, quando listamos seus elementos, ou por meio da compreensão, quando usamos uma propriedade que distingue seus elementos. Ao longo do ensino básico, você já deparou com isto. Vamos apenas relembrar.

Reescritos por extensão, esses conjuntos, em ordem, são lidos como:

  • {a,e,i,o,u}

  • {Atlético-PR,,Bahia,Botafogo,,Coritiba,,Fortaleza,,Internacional,,São Paulo,Sport,Vasco}

  • {Primavera,Verão,Outono,Inverno}

  • {Capitão,Kowalski,Recruta,Rico}

  • {2,4,6,8,10}

Já por compreensão, poderiam ser lidos como:

  • {cA;c é vogal}

  • {tT;t é da Série A}

  • {x;x é uma estação do ano}

  • {p;p é personagem do quarteto principal do filme Os Pinguins de Madagascar}

  • {e;e é estação do ano}

  • {nZ|n=2k2n10kZ}

Por livre conveniência, chamamos de A o conjunto de todas as letras de nosso alfabeto e de T o conjunto de todos os times de futebol do Brasil. Adicionalmente, vale ressaltar que poderíamos usar diferentes formas de denotá-los por compreensão além dessas. Tal liberdade de escolha, desde que coerente, transmite exatamente o caráter abstrato que a Matemática Discreta possui.

Estruturas de dados em Python para lidar com objetos discretos

A linguagem oferece diversos objetos para operarmos com quantidades discretas em formas de sequencias, listas ou coleções. De forma genérica, você pode interpretá-las como “conjuntos” que contém zero ou mais elementos. Um conjunto com zero elementos é chamado de vazio. Em Python, também temos meios para representar o “vazio” também, como veremos adiante.

As principais estruturas que aprenderemos serão:

  • list: estrutura cujo conteúdo é modificável e o tamanho variável. Listas são caracterizadas por mutabilidade e variabilidade. Objetos list são definidos por um par de colchetes e vírgulas que separam seus elementos: [., ., ... ,.].

  • tuple: estrutura cujo conteúdo não é modificável e o tamanho fixado. Tuplas são caracterizadas por imutabilidade e invariabilidade. Objetos tuple são definidos por um par de colchetes e vírgulas que separam seus elementos: (., ., ... ,.).

  • dict: estruturas contendo uma coleção de pares do tipo chave-valor. Dicionários são caracterizados por arrays associativos (tabelas hash). Objetos dict são definidos por um par de chaves e agrupamentos do tipo 'chave':valor (key:value), separados por vírgula: {'chave1':valor1, 'chave2':valor2, ... ,'chaven':valorn}. As chaves (keys) são do tipo str, ao passo que os valores podem ser de tipos arbitrários.

  • set: estruturas similares a dict, porém não possuem chaves e contêm objetos únicos. Conjuntos são caracterizadas por unicidade de elementos. Objetos set são definidos por um par de chaves e vírgulas que separam seus elementos: {., ., ... ,.}.

Listas

Estruturas list formam uma coleção de objetos arbitrários e podem ser criadas de modo sequenciado com operadores de pertencimento ou por expressões geradoras, visto que são estruturas iteráveis.

vogais = ['a','e','i','o','u']
vogais
Copy to clipboard
['a', 'e', 'i', 'o', 'u']
Copy to clipboard
times = ['Bahia', 'Sport', 'Fortaleza', 'Flamengo']
times
Copy to clipboard
['Bahia', 'Sport', 'Fortaleza', 'Flamengo']
Copy to clipboard
pares10 = [2,4,6,8,10]
pares10
Copy to clipboard
[2, 4, 6, 8, 10]
Copy to clipboard
mix = ['Bahia',24,6.54,[1,2]] # vários objetos na lista
mix
Copy to clipboard
['Bahia', 24, 6.54, [1, 2]]
Copy to clipboard

Listas por geração

Exemplo: crie uma lista dos primeiros 100 inteiros não-negativos.

os_100 = range(100) # range é uma função geradora
print(list(os_100)) # casting com 'list'
Copy to clipboard
[0, 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, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
Copy to clipboard

Exemplo: crie o conjunto {xZ;20x<10}

print(list(range(-20,10))) # print é usado para imprimir column-wise
Copy to clipboard
[-20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Copy to clipboard

Exemplo: crie o conjunto {xZ;20x10}

print(list(range(-20,11))) # para incluir 10, 11 deve ser o limite. Por quê?
Copy to clipboard
[-20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Copy to clipboard

Adicionando e removendo elementos

Há vários métodos aplicáveis para adicionar e remover elementos em listas.

Adição por apensamento

Adiciona elementos por concatenação no final da lista.

times.append('Botafogo')
times
Copy to clipboard
['Bahia', 'Sport', 'Fortaleza', 'Flamengo', 'Botafogo']
Copy to clipboard
times.append('Fluminense')
times
Copy to clipboard
['Bahia', 'Sport', 'Fortaleza', 'Flamengo', 'Botafogo', 'Fluminense']
Copy to clipboard

Adição por extensão

Para incluir elementos através de um objeto iterável, sequenciável, usamos extend.

times.extend(['Vasco, Atlético-MG']) # usa outra lista pra estender a lista
times
Copy to clipboard
['Bahia',
 'Sport',
 'Fortaleza',
 'Flamengo',
 'Botafogo',
 'Fluminense',
 'Vasco, Atlético-MG']
Copy to clipboard

Iteração e indexação

A iteração sobre uma lista é o processo de “passear” por seus elementos de modo sequenciado. Ao fornecermos o índice (posição) de seus elementos, podemos indexá-los.

Em Python, a indexação de listas começa a partir de 0 e termina em n - 1, onde n é o tamanho da lista.

Por exemplo, analise a seguinte correspondência:

posição:{p=0,p=1,,p=n1}

elementos na lista:[x1,x2,,xn]

Quer dizer, o primeiro elemento, x1 está na posição 0, p=0, ao passo que o último elemento, xn, está na posição n1, p=n1. Logo, se escolhermos uma variável chamada p que assume o valor 0, 1, …, n1, mediante a posição (ordenada) do elemento na lista, diremos que p é um iterador, os inteiros de 0 a n1 são os índices e n é o tamanho da lista.

Esta mesma idéia é aplicável a qualquer coleção, sequencia ou objeto iterável.

Remoção por índice

Suponha que tivéssemos criado a lista:

pares = [0,2,5,6] # 5 não é par
pares
Copy to clipboard
[0, 2, 5, 6]
Copy to clipboard

Como 5 não é par, não deveria estar na lista. Para excluírmos um elemento em uma posição específica, usamos pop passando o índice onde o elemento está.

pares.pop(2) # o ímpar 5 está na posição 2 e NÃO 3! 
pares
Copy to clipboard
[0, 2, 6]
Copy to clipboard

Adição por índice

Nesta lista, podemos pensar em incluir 4 entre 2 e 6. Para isto, usamos insert(posicao,valor), para valor na posicao desejada.

pares.insert(2,4) # 4 é inserido na posição de 6, que é deslocado
pares
Copy to clipboard
[0, 2, 4, 6]
Copy to clipboard

Apagar conteúdo da lista

Podemos apagar o conteúdo inteiro da lista com clear.

times.clear()
times # lista está vazia
Copy to clipboard
[]
Copy to clipboard

Podemos contar o número de elementos da lista com len.

len(times) # verifica que a lista está vazia
Copy to clipboard
0
Copy to clipboard
type([]) # a lista é vazia, mas continua sendo lista
Copy to clipboard
list
Copy to clipboard

Outros métodos de lista

Conte repetições de elementos na lista com count.

numeros = [1,1,2,3,1,2,4,5,6,3,4,4,5,5]
print( numeros.count(1), numeros.count(3), numeros.count(7) )
Copy to clipboard
3 2 0
Copy to clipboard

Localize a posição de um elemento com index.

numeros.index(5) # retorna a posição da primeira aparição
Copy to clipboard
7
Copy to clipboard

Remova a primeira aparição do elemento com remove.

numeros.remove(1) # perde apenas o primeiro
numeros
Copy to clipboard
[1, 2, 3, 1, 2, 4, 5, 6, 3, 4, 4, 5, 5]
Copy to clipboard

Faça uma reflexão (“flip”) in-place (sem criar nova lista) da lista com reverse.

numeros.reverse() 
numeros
Copy to clipboard
[5, 5, 4, 4, 3, 6, 5, 4, 2, 1, 3, 2, 1]
Copy to clipboard

Ordene a lista de maneira in-place (sem criar nova lista) com sort.

numeros.sort()
numeros
Copy to clipboard
[1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6]
Copy to clipboard

Concatenação de listas

Listas são concatenadas (“somadas”) com +. Caso já possua listas definidas, use extend.

['Flamengo', 'Botafogo'] + ['Fluminense']
Copy to clipboard
['Flamengo', 'Botafogo', 'Fluminense']
Copy to clipboard
['Flamengo', 'Botafogo'] + 'Fluminense' # erro: 'Fluminense' não é list
Copy to clipboard
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-23-3b000c9317b9> in <module>
----> 1 ['Flamengo', 'Botafogo'] + 'Fluminense' # erro: 'Fluminense' não é list

TypeError: can only concatenate list (not "str") to list
Copy to clipboard
times_nordeste = ['Fortaleza','Sport']
times_sul = ['Coritiba','Atlético-PR']
times_nordeste + times_sul
Copy to clipboard
['Fortaleza', 'Sport', 'Coritiba', 'Atlético-PR']
Copy to clipboard
times_nordeste.extend(times_sul) # mesma coisa
times_nordeste
Copy to clipboard
['Fortaleza', 'Sport', 'Coritiba', 'Atlético-PR']
Copy to clipboard

Fatiamento de listas

O fatiamento (“slicing”) permite que selecionemos partes da lista através do modelo start:stop, em que start é um índice incluído na iteração, e stop não.

letras = ['a','b','c','d','e','f','g']
letras[0:2]
Copy to clipboard
['a', 'b']
Copy to clipboard
letras[1:4]
Copy to clipboard
['b', 'c', 'd']
Copy to clipboard
letras[5:6]
Copy to clipboard
['f']
Copy to clipboard
letras[0:7] # toda a lista
Copy to clipboard
['a', 'b', 'c', 'd', 'e', 'f', 'g']
Copy to clipboard

Omissão de start e stop

letras[:3] # até 3, exclusive
Copy to clipboard
['a', 'b', 'c']
Copy to clipboard
letras[:5] # até 5, exclusive
Copy to clipboard
['a', 'b', 'c', 'd', 'e']
Copy to clipboard
letras[4:] # de 4 em diante
Copy to clipboard
['e', 'f', 'g']
Copy to clipboard
letras[6:] # de 6 em diante
Copy to clipboard
['g']
Copy to clipboard

Modo reverso

letras[-1] # último índice
Copy to clipboard
'g'
Copy to clipboard
letras[-2:-1] # do penúltimo ao último, exclusive
Copy to clipboard
['f']
Copy to clipboard
letras[-3:-1]
Copy to clipboard
['e', 'f']
Copy to clipboard
letras[-4:-2]
Copy to clipboard
['d', 'e']
Copy to clipboard
letras[-7:-1] # toda a lista
Copy to clipboard
['a', 'b', 'c', 'd', 'e', 'f']
Copy to clipboard
letras[-5:] 
Copy to clipboard
['c', 'd', 'e', 'f', 'g']
Copy to clipboard
letras[:-3] 
Copy to clipboard
['a', 'b', 'c', 'd']
Copy to clipboard

Elementos alternados com step

Podemos usar um dois pontos duplo (::) para dar um “passo” de alternância.

letras[::2] # salta 2-1 intermediários
Copy to clipboard
['a', 'c', 'e', 'g']
Copy to clipboard
letras[::3] # salta 3-1 intermediários
Copy to clipboard
['a', 'd', 'g']
Copy to clipboard
letras[::7] # salto de igual tamanho
Copy to clipboard
['a']
Copy to clipboard
letras[::8] # salto além do tamanho
Copy to clipboard
['a']
Copy to clipboard

Mutabilidade de listas

Podemos alterar o conteúdo de elementos diretamente por indexação.

from sympy.abc import x,y

ops = [x+y,x-y,x*y,x/y]
ops2 = ops.copy() # cópia de ops
ops
Copy to clipboard
[x + y, x - y, x*y, x/y]
Copy to clipboard
ops[0] = x-y
ops
Copy to clipboard
[x - y, x - y, x*y, x/y]
Copy to clipboard
ops[2] = x/y
ops
Copy to clipboard
[x - y, x - y, x/y, x/y]
Copy to clipboard
ops[1], ops[3] = x + y, x*y # mutação por desempacotamento
ops
Copy to clipboard
[x - y, x + y, x/y, x*y]
Copy to clipboard
ops[1:3] = [False, False, True] # mutação por fatiamento
ops
Copy to clipboard
[x - y, False, False, True, x*y]
Copy to clipboard
ops = ops2 # recuperando ops 
ops
Copy to clipboard
[x + y, x - y, x*y, x/y]
Copy to clipboard
ops2 is ops
Copy to clipboard
True
Copy to clipboard
ops3 = [] # lista vazia
ops3
Copy to clipboard
[]
Copy to clipboard
ops2 = ops + ops3 # concatenação cria uma lista nova
ops2
Copy to clipboard
[x + y, x - y, x*y, x/y]
Copy to clipboard
ops2 is ops # agora, ops2 não é ops 
Copy to clipboard
False
Copy to clipboard
print(id(ops), id(ops2)) # imprime local na memória de ambas
Copy to clipboard
140242443352016 140242447434608
Copy to clipboard
ops2 == ops # todos os elementos são iguais
Copy to clipboard
True
Copy to clipboard

O teste de identidade é False, mas o teste de igualdade é True.

Exemplo: Escreva uma função que calcule a área, perímetro, comprimento da diagonal, raio, perímetro e área do círculo inscrito, e armazene os resultados em uma lista.

# usaremos matemática simbólica
from sympy import symbols
from math import pi

# símbolos
B, H = symbols('B H',positive=True)

def propriedades_retangulo(B,H):
    '''
        A função assume que a base B 
        é maior do que a altura H. Senão, 
        as propriedades do círculo inscrito 
        não serão determinadas.        
    '''    
    d = (B**2 + H**2)**(1/2) # comprimento da diagonal
    r = d/2 # raio do círculo inscrito    
    return [B*H, 2*(B+H), d, d/2, 2*pi*r, pi*(r)**2]

# lista de objetos símbolos
propriedades_retangulo(B,H)
Copy to clipboard
[B*H,
 2*B + 2*H,
 (B**2 + H**2)**0.5,
 (B**2 + H**2)**0.5/2,
 3.14159265358979*(B**2 + H**2)**0.5,
 0.785398163397448*(B**2 + H**2)**1.0]
Copy to clipboard
# substituindo valores
B, H = 4.0, 2.5

# desempacotando
propriedades_retangulo(B,H)
Copy to clipboard
[10.0,
 13.0,
 4.716990566028302,
 2.358495283014151,
 14.818862909286873,
 17.47510913559322]
Copy to clipboard

Formatação de strings

Os valores na lista acima poderiam ser impressos de uma maneira mais legível. Até o momento, estivemos habituados em imprimir valores passando-s à função print. Entretanto, a Python nos oferece uma ampla gama de recursos para formatar strings. Veremos mais detalhes sobre templating e formatação de strings mais à frente no curso. Por enquanto, vamos ver como podemos imprimir melhor os float anteriores.

O template a seguir usa a função format para substituição de valores indexados.

templ = '{0} {1} ... {n}'.format(arg0,arg1,...,argn)
Copy to clipboard

Nota: Para ajuda plena sobre formatação, consultar:

help('FORMATTING')
Copy to clipboard
# considere R: retângulo; C: círculo inscrito

res = propriedades_retangulo(B,H) # resultado

props = ['Área de R',
         'Perímetro de R',
         'Diagonal de R',
         'Raio de C',
         'Perímetro de C',
         'Área de C'
        ] # propriedades

# template
templ = '{0:s} = {1:.2f}\n\
{2:s} = {3:.3f}\n\
{4:s} = {5:.4f}\n\
{6:s} = {7:.5f}\n\
{8:s} = {9:.6f}\n\
{10:s} = {11:.7f}'.format(props[0],res[0],\
                          props[1],res[1],\
                          props[2],res[2],\
                          props[3],res[3],\
                          props[4],res[4],\
                          props[5],res[5])

# impressão formatada
print(templ)
Copy to clipboard
Área de R = 10.00
Perímetro de R = 13.000
Diagonal de R = 4.7170
Raio de C = 2.35850
Perímetro de C = 14.818863
Área de C = 17.4751091
Copy to clipboard

Como interpretar o que fizemos?

  • {0:s} formata o primeiro argumento de format, o qual é props[0], como str (s).

  • {1:.2f} formata o segundo argumento de format, o qual é res[0], como float (f) com duas casas decimais (.2).

  • {3:.3f} formata o quarto argumento de format, o qual é res[1], como float (f) com três casas decimais (.3).

A partir daí, percebe-se que um template {X:.Yf} diz para formatar o argumento X como float com Y casas decimais, ao passo que o template {X:s} diz para formatar o argumento X como str.

Além disso, temos:

  • \n, que significa “newline”, isto é, uma quebra da linha.

  • \, que é um caracter de escape para continuidade da instrução na linha seguinte. No exemplo em tela, o template criado é do tipo multi-line.

Nota: a contrabarra em \n também é um caracter de escape e não um caracter literal. Isto é, para imprimir uma contrabarra literalmente, é necessário fazer \\. Vejamos exemplos de literais a seguir.

Exemplos de impressão de caracteres literais

print('\\') # imprime contrabarra literal
print('\\\\') # imprime duas contrabarras literais
print('\'') # imprime plica
print('\"') # imprime aspas
Copy to clipboard
\
\\
'
"
Copy to clipboard

f-strings

Temos uma maneira bastante interessante de criar templates usando f-strings, que foi introduzida a partir da versão Python 3.6. Com f-strings a substituição é imediata.

print(f'{props[0]} = {res[0]}') # estilo f-string
Copy to clipboard
Área de R = 10.0
Copy to clipboard

Estilos de formatação

Veja um comparativo de estilos:

print('%s = %f ' % (props[0], res[0])) # Python 2
print('{} = {}'.format(props[0], res[0])) # Python 3
print('{0:s} = {1:.4f}'.format(props[0], res[0])) # Python 3 formatado
Copy to clipboard
Área de R = 10.000000 
Área de R = 10.0
Área de R = 10.0000
Copy to clipboard

Exemplo: Considere o conjunto: V = {cA;c é vogal}. Crie a concatenação de todos os elementos com f-string.

V = ['a','e','i','o','u']
V
Copy to clipboard
['a', 'e', 'i', 'o', 'u']
Copy to clipboard
f'{V[0]}{V[1]}{V[2]}{V[3]}{V[4]}' # pouco Pythônico
Copy to clipboard
'aeiou'
Copy to clipboard

Veremos à frente meios mais elegantes de fazer coisas similares.

Controle de fluxo: laço for

Em Python, podemos realizar iterar por uma coleção ou iterador usando laços. Introduziremos aqui o laço for. Em Python, o bloco padrão para este laço é dado por:

for valor in sequencia:
    # faça algo com valor
Copy to clipboard

Acima, valor é um iterador.

for v in vogais: # itera sobre lista inteira
    print(v)
Copy to clipboard
a
e
i
o
u
Copy to clipboard
for v in vogais[0:3]: # itera parcialmente
    print(v + 'a')
Copy to clipboard
aa
ea
ia
Copy to clipboard
for v in vogais[-2:]: 
    print(f'{v*10}')
Copy to clipboard
oooooooooo
uuuuuuuuuu
Copy to clipboard

Compreensão de lista

Usando for, a criação de listas torna-se bastante facilitada.

Exemplo: crie a lista dos primeiros 10 quadrados perfeitos.

Q = [q*q for q in range(1,11)]
Q
Copy to clipboard
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
Copy to clipboard

A operação acima equivale a:

Q2 = []
for q in range(1,11):
    Q2.append(q*q)
Q2        
Copy to clipboard
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
Copy to clipboard

Exemplo: crie a PA: an=3+6(n1),1n10

PA = [3 + 6*(n-1) for n in range(1,11) ]
PA
Copy to clipboard
[3, 9, 15, 21, 27, 33, 39, 45, 51, 57]
Copy to clipboard

Exemplo: se X={1,2,3} e Y={4,5,6}, cria a “soma” X+Y elemento a elemento.

X = [1,2,3]
Y = [4,5,6]

XsY = [ X[i] + Y[i] for i in range(len(X)) ]
XsY
Copy to clipboard
[5, 7, 9]
Copy to clipboard

Exemplo: se X={1,2,3} e Y={4,5,6}, cria o “produto” XY elemento a elemento.

XpY = [ X[i]*Y[i] for i in range(len(X)) ]
XpY
Copy to clipboard
[4, 10, 18]
Copy to clipboard

Tuplas

Tuplas são são sequencias imutáveis de tamanho fixo. Em Matemática, uma tupla é uma sequência ordenada de elementos. Em geral, o termo nupla (“ênupla”) é usado para se referir a uma tupla com n elementos.

Por exemplo, tuplas de um único elemento são chamadas de “singleton” ou “mônada”. Tuplas de dois elementos são os conhecidos “pares ordenados”. Com três elementos, chamamos de “trio” ou “tripleta”, e assim por diante.

Em Python, tuplas são criadas naturalmente sequenciando elementos.

par = 1,2; par
Copy to clipboard
(1, 2)
Copy to clipboard
trio = (1,2,3); trio
Copy to clipboard
(1, 2, 3)
Copy to clipboard
quad = (1,2,3,4); quad
Copy to clipboard
(1, 2, 3, 4)
Copy to clipboard
nome = 'Nome'; tuple(nome) # casting
Copy to clipboard
('N', 'o', 'm', 'e')
Copy to clipboard

Tuplas são acessíveis por indexação.

quad[1]
Copy to clipboard
2
Copy to clipboard
quad[1:4]
Copy to clipboard
(2, 3, 4)
Copy to clipboard
quad[3] = 5 # tuplas não são mutáveis
Copy to clipboard
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-79-59bcf52d23f3> in <module>
----> 1 quad[3] = 5 # tuplas não são mutáveis

TypeError: 'tuple' object does not support item assignment
Copy to clipboard

Se na tupla houver uma lista, a lista é modificável.

super_trio = tuple([1,[2,3],4]) # casting
super_trio
Copy to clipboard
(1, [2, 3], 4)
Copy to clipboard
super_trio[1].extend([4,5]) 
super_trio
Copy to clipboard
(1, [2, 3, 4, 5], 4)
Copy to clipboard

Tuplas também são concatenáveis com +.

(2,3) + (4,3)
Copy to clipboard
(2, 3, 4, 3)
Copy to clipboard
('a',[1,2],(1,1))*2 # repetição
Copy to clipboard
('a', [1, 2], (1, 1), 'a', [1, 2], (1, 1))
Copy to clipboard

Desempacotamento de tuplas

a,b,c,d = (1,2,3,4)
Copy to clipboard
for i in [a,b,c,d]:
    print(i) # valor das variáveis
Copy to clipboard
1
2
3
4
Copy to clipboard
a,b = (1,2)
a,b = b,a # troca de valores
a,b
Copy to clipboard
(2, 1)
Copy to clipboard

enumerate

Podemos controlar índice e valor ao iterar em uma sequencia.

for i,x in enumerate(X): # (i,x) é uma tupla (índice,valor)
    print(f'{i} : {x}')
Copy to clipboard
0 : 1
1 : 2
2 : 3
Copy to clipboard

Exemplo: Construa o produto cartesiano

A×B={(a,b)Z×Z;4a43a7}
AB = ([(a,b) for a in range(-4,4) for b in range(3,7)])
print(AB)
Copy to clipboard
[(-4, 3), (-4, 4), (-4, 5), (-4, 6), (-3, 3), (-3, 4), (-3, 5), (-3, 6), (-2, 3), (-2, 4), (-2, 5), (-2, 6), (-1, 3), (-1, 4), (-1, 5), (-1, 6), (0, 3), (0, 4), (0, 5), (0, 6), (1, 3), (1, 4), (1, 5), (1, 6), (2, 3), (2, 4), (2, 5), (2, 6), (3, 3), (3, 4), (3, 5), (3, 6)]
Copy to clipboard

Dicionários

Dicionários, ou especificamente, objetos dict, possuem extrema versatilidade e são muito poderosos. Criamos um dict por diversas formas. A mais simples é usar chaves e pares explícitos.

d = {} # dict vazio
d
Copy to clipboard
{}
Copy to clipboard
type(d)
Copy to clipboard
dict
Copy to clipboard

Os pares chave-valor incorporam quaisquer tipos de dados.

d = {'par': [0,2,4,6,8], 'ímpar': [1,3,5,7,9], 'nome':'Meu dict', 'teste': True}
d
Copy to clipboard
{'par': [0, 2, 4, 6, 8],
 'ímpar': [1, 3, 5, 7, 9],
 'nome': 'Meu dict',
 'teste': True}
Copy to clipboard

Acesso a conteúdo

Para acessar o conteúdo de uma chave, indexamos pelo seu nome.

d['par'] 
Copy to clipboard
[0, 2, 4, 6, 8]
Copy to clipboard
d['nome']
Copy to clipboard
'Meu dict'
Copy to clipboard

Exemplo: construindo soma e multiplicação especial.

# dict
op = {'X' :[1,2,3], 'delta' : 0.1}

# função
def sp(op):
    s = [x + op['delta'] for x in op['X']]
    p = [x * op['delta'] for x in op['X']]
    
    return (s,p) # retorna tupla

soma, prod = sp(op) # desempacota

for i,s in enumerate(soma):
    print(f'pos({i}) | Soma = {s} | Prod = {prod[i]}')
Copy to clipboard
pos(0) | Soma = 1.1 | Prod = 0.1
pos(1) | Soma = 2.1 | Prod = 0.2
pos(2) | Soma = 3.1 | Prod = 0.30000000000000004
Copy to clipboard

Inserção de conteúdo

# apensa variáveis
op[1] = 3 
op['novo'] = (3,4,1) 
op
Copy to clipboard
{'X': [1, 2, 3], 'delta': 0.1, 1: 3, 'novo': (3, 4, 1)}
Copy to clipboard

Alteração de conteúdo

op['novo'] = [2,1,4] # sobrescreve
op
Copy to clipboard
{'X': [1, 2, 3], 'delta': 0.1, 1: 3, 'novo': [2, 1, 4]}
Copy to clipboard

Deleção de conteúdo com del e pop

del op[1] # deleta chave 
op
Copy to clipboard
{'X': [1, 2, 3], 'delta': 0.1, 'novo': [2, 1, 4]}
Copy to clipboard
novo = op.pop('novo') # retorna e simultaneamente deleta
novo
Copy to clipboard
[2, 1, 4]
Copy to clipboard
op
Copy to clipboard
{'X': [1, 2, 3], 'delta': 0.1}
Copy to clipboard

Listagem de chaves e valores

Usamos os métodos keys() e values() para listar chaves e valores.

arit = {'soma': '+', 'subtr': '-', 'mult': '*', 'div': '/'} # dict

k = list(arit.keys())
print(k)
val = list(arit.values())
print(val)
for v in range(len(arit)):
    print(f'A operação \'{k[v]}\' de "arit" usa o símbolo \'{val[v]}\'.')
Copy to clipboard
['soma', 'subtr', 'mult', 'div']
['+', '-', '*', '/']
A operação 'soma' de "arit" usa o símbolo '+'.
A operação 'subtr' de "arit" usa o símbolo '-'.
A operação 'mult' de "arit" usa o símbolo '*'.
A operação 'div' de "arit" usa o símbolo '/'.
Copy to clipboard

Combinando dicionários

Usamos update para combinar dicionários. Este método possui um resultado similar a extend, usado em listas.

pot = {'pot': '**'}
arit.update(pot)
arit
Copy to clipboard
{'soma': '+', 'subtr': '-', 'mult': '*', 'div': '/', 'pot': '**'}
Copy to clipboard

Dicionários a partir de sequencias

Podemos criar dicionários a partir de sequencias existentes usando zip.

arit = {'soma', 'subtr', 'mult', 'div', 'pot'} 
ops = {'+', '-', '*', '/', '**'}

dict_novo = {}

for chave,valor in zip(arit,ops):
    dict_novo[chave] = valor
    
dict_novo
Copy to clipboard
{'soma': '-', 'div': '*', 'pot': '/', 'mult': '+', 'subtr': '**'}
Copy to clipboard

Visto que um dict é composto de várias tuplas de 2, podemos criar um de maneira ainda mais simples.

dict_novo = dict(zip(arit,ops)) # visto que dicts
dict_novo
Copy to clipboard
{'soma': '-', 'div': '*', 'pot': '/', 'mult': '+', 'subtr': '**'}
Copy to clipboard

Controle de fluxo: condicionais if, elif e else

Em Python, como na maioria das linguagens, o operador if (“se”) serve para tratar situações quando um bloco de instruções de código precisa ser executado apenas se uma dada condição estabelecida for avaliada como verdadeira. Um bloco condicional é escrito da seguinte forma:

if condição:
    # faça algo
Copy to clipboard

Este bloco diz basicamente o seguinte: “faça algo se a condição for verdadeira”. Vejamos alguns exemplos.

if 2 > 0: # a condição é 'True'
    print("2 é maior do que 0!") 
Copy to clipboard
2 é maior do que 0!
Copy to clipboard
2 > 0 # esta é a condição que está sendo avaliada
Copy to clipboard
True
Copy to clipboard
if 2 < 1: # nada é impresso porque a condição é 'False'
    print("2 é maior do que 0!") 
Copy to clipboard
2 < 1 # esta é a condição que está sendo avaliada
Copy to clipboard
False
Copy to clipboard

A condição pode ser formada de diversas formas desde que possa ser avaliada como True ou False.

x, y = 2, 4
if x < y:
    print(f'{x} < {y}')
Copy to clipboard
2 < 4
Copy to clipboard

A estrutura condicional pode ser ampliada com um ou mais elif (“ou se”) e com else (senão). Cada elif, uma redução de else if, irá testar uma condição adicional se a condição relativa a if for False. Se alguma delas for testada como True, o bloco de código correspondende será executado. Caso contrário, a decisão do interpretador será executar o bloco que acompanhará else.

Exemplo: teste da tricotomia. Verificar se um número é >, < ou =0.

x = 4.1 # número para teste

if x < 0: # se
    print(f'{x} < 0')
elif x > 0: # ou se
    print(f'{x} > 0')
else: # senão
    print(f'{x} = 0')
Copy to clipboard
4.1 > 0
Copy to clipboard

Exemplo: Considere o conjunto de classificações sanguíneas ABO (+/-)

S={A+,A-,B+,B-,AB+,AB-,O+,O-}

Se em um experimento aleatório, n pessoas (n500) diferentes entrassem por um hospital em um único dia, qual seria a probabilidade de p entre as n pessoas serem classificadas como um(a) doador(a) universal (sangue O-) naquele dia? Em seguida, estime a probabilidade das demais.

# 'randint' gera inteiros aleatoriamente
from random import randint 

# número de pessoas
n = 500 

# associa inteiros 0-7 ao tipo sanguíneo
tipos = [i for i in range(0,8)]
sangue = dict(zip(tipos,['A+','A-','B+','B-','AB+','AB-','O+','O-']))

# primeira pessoa
i = randint(0,8) 

# grupo sanguíneo
s = [] 

# repete n vezes
for _ in range(0,n): 
    if i == 0:
        s.append(0)
    elif i == 1:
        s.append(1)
    elif i == 2:
        s.append(2)
    elif i == 3:
        s.append(3)
    elif i == 4:
        s.append(4)
    elif i == 5:
        s.append(5)
    elif i == 6:
        s.append(6)
    else:
        s.append(7)
        
    i = randint(0,7) # nova pessoa

# calcula a probabilidade do tipo p em %.
# Seria necessário definir uma lambda? 
prob = lambda p: p/n*100
        
# armazena probabilidades no dict P
P = {}
for tipo in tipos:
    P[tipo] = prob(s.count(tipo))
    if sangue[tipo] == 'O-':
        print('A probabilidade de ser doador universal é de {0:.2f}%.'.format(P[tipo]))        
    else:
        print('A probabilidade de ser {0:s} é de {1:.2f}%.'.format(sangue[tipo],P[tipo]))                        
Copy to clipboard
A probabilidade de ser A+ é de 10.80%.
A probabilidade de ser A- é de 14.00%.
A probabilidade de ser B+ é de 15.00%.
A probabilidade de ser B- é de 12.80%.
A probabilidade de ser AB+ é de 12.80%.
A probabilidade de ser AB- é de 13.60%.
A probabilidade de ser O+ é de 11.00%.
A probabilidade de ser doador universal é de 10.00%.
Copy to clipboard

Conjuntos

As estruturas set (conjunto) são úteis para realizar operações com conjuntos.

set(['a','b','c']) # criando por função
Copy to clipboard
{'a', 'b', 'c'}
Copy to clipboard
{'a','b','c'} # criando de modo literal
Copy to clipboard
{'a', 'b', 'c'}
Copy to clipboard
{1,2,2,3,3,4,4,4} # 'set' possui unicidade de elementos
Copy to clipboard
{1, 2, 3, 4}
Copy to clipboard

União de conjuntos

Considere os seguintes conjuntos.

A = {1,2,3}
B = {3,4,5}
C = {6}
Copy to clipboard
A.union(B) # união
Copy to clipboard
{1, 2, 3, 4, 5}
Copy to clipboard
A | B # união com operador alternativo ('ou')
Copy to clipboard
{1, 2, 3, 4, 5}
Copy to clipboard

Atualização de conjuntos (união)

A união in-place de dois conjuntos pode ser feita com update.

C
Copy to clipboard
{6}
Copy to clipboard
C.update(B) # C é atualizado com elementos de B
C
Copy to clipboard
{3, 4, 5, 6}
Copy to clipboard
C.union(A) # conjunto união com A
Copy to clipboard
{1, 2, 3, 4, 5, 6}
Copy to clipboard
C # os elementos de A não foram atualizados em C
Copy to clipboard
{3, 4, 5, 6}
Copy to clipboard

A atualização da união possui a seguinte forma alternativa com |=.

C |= A # elementos de A atualizados em C
C
Copy to clipboard
{1, 2, 3, 4, 5, 6}
Copy to clipboard

Interseção de conjuntos

A.intersection(B) # interseção
Copy to clipboard
{3}
Copy to clipboard
A & B # interseção com operador alternativo ('e')
Copy to clipboard
{3}
Copy to clipboard

Atualização de conjuntos (interseção)

A interseção in-place de dois conjuntos pode ser feita com intersection_update.

D = {1, 2, 3, 4}
E = {2, 3, 4, 5}
Copy to clipboard
D.intersection(E) # interseção com E
Copy to clipboard
{2, 3, 4}
Copy to clipboard
D # D inalterado
Copy to clipboard
{1, 2, 3, 4}
Copy to clipboard
D.intersection_update(E) 
D # D alterado
Copy to clipboard
{2, 3, 4}
Copy to clipboard

A atualização da interseção possui a seguinte forma alternativa com &=.

D &= E
D
Copy to clipboard
{2, 3, 4}
Copy to clipboard

Diferença entre conjuntos

A
Copy to clipboard
{1, 2, 3}
Copy to clipboard
D
Copy to clipboard
{2, 3, 4}
Copy to clipboard
A.difference(D) # apenas elementos de A
Copy to clipboard
{1}
Copy to clipboard
D.difference(A) # apenas elementos de D
Copy to clipboard
{4}
Copy to clipboard
A - D # operador alternativo 
Copy to clipboard
{1}
Copy to clipboard
D - A 
Copy to clipboard
{4}
Copy to clipboard

Atualização de conjuntos (diferença)

A interseção in-place de dois conjuntos pode ser feita com difference_update.

D = {1, 2, 3, 4}
E = {1, 2, 3, 5}
Copy to clipboard
D
Copy to clipboard
{1, 2, 3, 4}
Copy to clipboard
D.difference(E)
D
Copy to clipboard
{1, 2, 3, 4}
Copy to clipboard
D.difference_update(E)
D
Copy to clipboard
{4}
Copy to clipboard

A atualização da diferença possui a seguinte forma alternativa com -=.

D -= E
D
Copy to clipboard
{4}
Copy to clipboard

Adição ou remoção de elementos

A
Copy to clipboard
{1, 2, 3}
Copy to clipboard
A.add(4) # adiciona 4 a A
A
Copy to clipboard
{1, 2, 3, 4}
Copy to clipboard
B
Copy to clipboard
{3, 4, 5}
Copy to clipboard
B.remove(3) # remove 3 de B
B
Copy to clipboard
{4, 5}
Copy to clipboard

Reinicialização de um conjunto (vazio)

Podemos remover todos os elementos de um conjunto com clear, deixando-o em um estado vazio.

A
Copy to clipboard
{1, 2, 3, 4}
Copy to clipboard
A.clear()
A # A é vazio
Copy to clipboard
set()
Copy to clipboard
len(A) # 0 elementos
Copy to clipboard
0
Copy to clipboard

Diferença simétrica

A diferença simétrica entre dois conjuntos A e B é dada pela união dos complementares relativos:

AB=ABBA

Logo, em AB estarão todos os elementos que pertencem a A ou a B mas não aqueles que são comuns a ambos.

Nota: os complementares relativos AB e BA aqui podem ser interpretados como AB e BA. Os símbolos e em conjuntos podem ter sentidos diferentes em alguns contextos.

G = {1,2,3,4}
H = {3,4,5,6}
Copy to clipboard
G.symmetric_difference(H) # {3,4} ficam de fora, pois são interseção
Copy to clipboard
{1, 2, 5, 6}
Copy to clipboard
G ^ H # operador alternativo
Copy to clipboard
{1, 2, 5, 6}
Copy to clipboard

Atualização de conjuntos (diferença simétrica)

A diferença simétrica in-place de dois conjuntos pode ser feita com symmetric_difference_update.

G
Copy to clipboard
{1, 2, 3, 4}
Copy to clipboard
G.symmetric_difference_update(H)
G # alterado
Copy to clipboard
{1, 2, 5, 6}
Copy to clipboard
G ^= H # operador alternativo
G
Copy to clipboard
{1, 2, 3, 4}
Copy to clipboard

Continência

Podemos verificar se um conjunto A é subconjunto de (está contido em) outro conjunto B (AB) ou se B é um superconjunto para (contém) A (BA) com issubset e issuperset.

B
Copy to clipboard
{4, 5}
Copy to clipboard
C
Copy to clipboard
{1, 2, 3, 4, 5, 6}
Copy to clipboard
B.issubset(C) # B está contido em C
Copy to clipboard
True
Copy to clipboard
C.issuperset(B) # C contém B
Copy to clipboard
True
Copy to clipboard

Subconjuntos e subconjuntos próprios

Podemos usar operadores de comparação entre conjuntos para verificar continência.

  • AB: A é subconjunto de B

  • AB: A é subconjunto próprio de B (A possui elementos que não estão em B)

{1,2,3} <= {1,2,3} # subconjunto
Copy to clipboard
True
Copy to clipboard
{1,2} < {1,2,3} # subconjunto próprio
Copy to clipboard
True
Copy to clipboard
{1,2,3} > {1,2}
Copy to clipboard
True
Copy to clipboard
{1,2} >= {1,2,3}
Copy to clipboard
False
Copy to clipboard

Disjunção

Dois conjuntos são disjuntos se sua interseção é vazia. Podemos verificar a disjunção com isdisjoint

E
Copy to clipboard
{1, 2, 3, 5}
Copy to clipboard
G
Copy to clipboard
{1, 2, 3, 4}
Copy to clipboard
E.isdisjoint(G) 1,2,5 são comuns
Copy to clipboard
  File "<ipython-input-163-89ce3afb7e04>", line 1
    E.isdisjoint(G) 1,2,5 são comuns
                    ^
SyntaxError: invalid syntax
Copy to clipboard
D
Copy to clipboard
{4}
Copy to clipboard
E.isdisjoint(D)
Copy to clipboard
True
Copy to clipboard
A
Copy to clipboard
set()
Copy to clipboard
E.isdisjoint(A)
Copy to clipboard
True
Copy to clipboard

Igualdade entre conjuntos

Dois conjuntos são iguais se contém os mesmos elementos.

H = {3,'a', 2}
I = {'a',2, 3}
J = {1,'a'}
Copy to clipboard
H == I
Copy to clipboard
True
Copy to clipboard
H == J
Copy to clipboard
False
Copy to clipboard
{1,2,2,3} == {3,3,3,2,1} # lembre-se da unicidade
Copy to clipboard
True
Copy to clipboard

Compreensão de conjunto

Podemos usar for para criar conjuntos de maneira esperta do mesmo modo que as compreensões de lista e de dicionários. Neste caso, o funcionamento é como list, porém, em vez de colchetes, usamos chaves.

{e for e in range(0,10)}
Copy to clipboard
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
Copy to clipboard
{(i,v) for (i,v) in enumerate(range(0,4))}
Copy to clipboard
{(0, 0), (1, 1), (2, 2), (3, 3)}
Copy to clipboard

Sobrecarga de operadores

Em Python, podemos realizar alguns procedimentos úteis para laços de repetição.

x = 2
x += 1 # x = 2 + 1 (incrementação)
x
Copy to clipboard
3
Copy to clipboard
y = 3
y -= 1 # y = 3 - 1 (decrementação)
y
Copy to clipboard
2
Copy to clipboard
z = 2
z *= 2 # z = 2*2
z
Copy to clipboard
4
Copy to clipboard
t = 3
t /= 3 # t = 3/3
t
Copy to clipboard
1.0
Copy to clipboard

Exemplo: verifique se a soma das probabilidades no dict P do experimento aleatório é realmente 100%.

s = 0
for p in P.values(): # itera sobre os valores de P
    s += p # soma cumulativa
print(f'A soma de P é {s}%')
Copy to clipboard
A soma de P é 100.0%
Copy to clipboard

De modo mais Pythônico:

sum(P.values()) == 100
Copy to clipboard
True
Copy to clipboard

Ou ainda:

if sum(P.values()) == 100:
    print(f'A soma de P é {s}%')
else:
    print(f'Há erro no cálculo!')        
Copy to clipboard
A soma de P é 100.0%
Copy to clipboard

Controle de fluxo: laço while

O condicional while permite que um bloco de código seja repetidamente executado até que uma dada condição seja avaliada como False, ou o laço seja explicitamente terminado com a keyword break. Em laços while, é muito comum usar uma linha de atualização da condição usando sobrecarga de operadores.

A instrução é como segue:

while condicao:
    # faça isso 
    # atualize condicao
Copy to clipboard
x = 10
boom = 0
while x > boom: # não leva em conta igualdade
    print(x)
    x -= 1 # atualizando por decrementação
print('Boom!') 
Copy to clipboard
10
9
8
7
6
5
4
3
2
1
Boom!
Copy to clipboard
x = 5
boom = 10
while x <= boom: # leva em conta igualdade
    print(x) 
    x += 0.5 # atualizando por incrementação   
Copy to clipboard
5
5.5
6.0
6.5
7.0
7.5
8.0
8.5
9.0
9.5
10.0
Copy to clipboard
from math import sin,pi
x = 1.0
i = 1
while x**3 > 0:
    if i % 100 == 0: # imprime apenas a cada 1000 repetições
        print(f'Repeti {i} vezes e x = {x**3}. Contando...')     
    x -= 1e-3  # atualiza o decremento
    i += 1 # contagem de repetição
print(f'x = {x**3}')
Copy to clipboard
Repeti 100 vezes e x = 0.7314327009999998. Contando...
Repeti 200 vezes e x = 0.5139224009999996. Contando...
Repeti 300 vezes e x = 0.3444721009999996. Contando...
Repeti 400 vezes e x = 0.2170818009999996. Contando...
Repeti 500 vezes e x = 0.12575150099999965. Contando...
Repeti 600 vezes e x = 0.06448120099999974. Contando...
Repeti 700 vezes e x = 0.02727090099999983. Contando...
Repeti 800 vezes e x = 0.008120600999999913. Contando...
Repeti 900 vezes e x = 0.0010303009999999755. Contando...
Repeti 1000 vezes e x = 9.999999999973564e-10. Contando...
x = -6.8435572439409775e-46
Copy to clipboard
from math import sin,pi
x = 1.0
i = 1
while x**3 > 0:
    if i % 100 == 0: # imprime apenas a cada 1000 repetições
        print(f'Repeti {i} vezes e x = {x**3}. Contando...')    
    if i == 500:
        print(f'Repeti demais. Vou parar.')  
        break # execução interrompida aqui       
    x -= 1e-3  # atualiza o decremento
    i += 1 # contagem de repetição
print(f'x = {x**3}')
Copy to clipboard
Repeti 100 vezes e x = 0.7314327009999998. Contando...
Repeti 200 vezes e x = 0.5139224009999996. Contando...
Repeti 300 vezes e x = 0.3444721009999996. Contando...
Repeti 400 vezes e x = 0.2170818009999996. Contando...
Repeti 500 vezes e x = 0.12575150099999965. Contando...
Repeti demais. Vou parar.
x = 0.12575150099999965
Copy to clipboard

Exemplo: construa seu próprio gerador de números aleatórios para o problema da entrada de pessoas no hospital.

# exemplo simples
def meu_gerador():
    nums = []
    while True: # executa indefinidamente até se digitar ''
        entr = input() # entrada do usuário            
        nums.append(entr) # armazena         
        if entr == '': # pare se nada mais for inserido
            return list(map(int,nums[:-1])) # converte para int e remove '' da lista
Copy to clipboard
# execução: 
# 2; shift+ENTER; para 2
# 3; shift+ENTER; para 3
# 4; shift+ENTER; para 4
# shift+ENTER; para nada
nums = meu_gerador() 
nums
Copy to clipboard
 2
 3
 4
 
Copy to clipboard
[2, 3, 4]
Copy to clipboard

Exemplo: verifique se a soma das probabilidades no dict P do experimento aleatório é realmente 100%.

sum(P.values())
Copy to clipboard
100.0
Copy to clipboard

map

A função map serve para construir uma função que será aplicada a todos os elementos de uma sequencia. Seu uso é da seguinte forma:

map(funcao,sequencia)
Copy to clipboard

No exemplo anterior, as entradas do usuário são armazenadas como str, isto é, ‘2’, ‘3’ e ‘4’. Para que elas sejam convertidas para int, nós executamos um casting em todos os elementos da sequencia usando map.

A interpretação é a seguinte: para todo x pertencente a sequencia, aplique funcao(x). Porém, para se obter o resultado desejado, devemos ainda aplicar list sobre o map.

nums = ['2','3','4']
nums
Copy to clipboard
['2', '3', '4']
Copy to clipboard
m = map(int,nums) # aplica a função 'int' aos elementos de 'num'
m
Copy to clipboard
<map at 0x7f8cbbb32810>
Copy to clipboard

Observe que a resposta de map não é human-readable. Para lermos o que queremos, fazemos:

l = list(m) # aplica 'list' sobre 'map'
l
Copy to clipboard
[2, 3, 4]
Copy to clipboard

Podemos substituir funcao por uma função anônima. Assim, suponha que você quisesse enviezar os valores de entrada somando 1 a cada número. Poderíamos fazer isso como:

list(map(lambda x: x**2,l)) # eleva elementos ao quadrado
Copy to clipboard
[4, 9, 16]
Copy to clipboard

filter

Podemos aplicar também como uma espécie de “filtro” para valores usando a função filter. No caso anterior, digamos que valores acima de 7 sejam inseridos erroneamente no gerador de números (lembre-se que no sistema sanguíneo ABO, consideramos um dict cujo valor das chaves é no máximo 7). Podemos, ainda assim, filtrar a lista para coletar apenas valores menores do que 7. Para tanto, definimos uma função lambda com este propósito.

lista_erronea = [2,9,4,6,7,1,9,10,2,4,5,2,7,7,11,7,6]
lista_erronea
Copy to clipboard
[2, 9, 4, 6, 7, 1, 9, 10, 2, 4, 5, 2, 7, 7, 11, 7, 6]
Copy to clipboard
f = filter(lambda x: x <= 7, lista_erronea) # aplica filtro
f
Copy to clipboard
<filter at 0x7f8cbd4d7450>
Copy to clipboard
lista_corrigida = list(f) # valores > 7 excluídos
lista_corrigida
Copy to clipboard
[2, 4, 6, 7, 1, 2, 4, 5, 2, 7, 7, 7, 6]
Copy to clipboard

Exemplos com maior complexidade

Exemplo: Podemos escrever outro gerador de forma mais complexa. Estude este caso (pouco Pythônico).

import random

la = random.sample(range(0,1000),1000) # escolhe 1000 números numa lista aleatória de 0 a 1000
teste = lambda x: -1 if x >= 8 else x # retorna x no intervalo [0,7], senão o próprio número
f = list(map(teste,la))
final = list(filter(lambda x: x != -1,f)) # remove > 8
final
Copy to clipboard
[0, 7, 4, 1, 5, 6, 2, 3]
Copy to clipboard

Exemplo: Associando arbitrariamente o identificador de uma pessoa a um tipo sanguíneo com compreensão de dict.

id_pessoas = {chave:x for chave,x in enumerate(f) if x > -1} # compreensão de dicionário com if
id_pessoas
Copy to clipboard
{77: 0, 100: 7, 191: 4, 313: 1, 357: 5, 669: 6, 854: 2, 919: 3}
Copy to clipboard