Sobre tuplas e Zips
Algumas propriedades extras sobre tuplas são listadas aqui. Além disso usamos a fução zip() para unir objetos iteráveis de modo a poderem ser percorridos simultaneamante.
# Uma tupla não precisa de parenteses » t = 1, 2, 3, 4 » t ↳ (1, 2, 3, 4) » type(t) ↳ tuple # podemos usar tuplas para declarações múltiplas » x, y = 45, 78 » print(x,y, x+y) ↳ 45 78 123 # E percorrer uma tupla (ou lista) em um loop for » t = [('a', 0, True), ('b', 1, False), ('c', 2, True)] » for letra, num, b in t: » if b: print (num, letra) ↳ 0 a ↳ 2 c # qualquer sequência pode ser usada no construtor de tuplas » t = tuple('palavras') » t ↳ ('p', 'a', 'l', 'a', 'v', 'r', 'a', 's') # uma tupla de 1 elemento deve conter (,) » t = ('a',) » t ↳ ('a',) » type(t) ↳ tuple # tuplas para 'swap' de variáveis » a = 'both' » b = 'ambos' print(a,b) ↳ both ambos » a, b = b, a » print(a,b) ↳ ambos both
Funções retornam uma variável ou None. No entanto essa variável pode ser uma tupla, um dicionário ou outro objeto qualquer, o que tem o efeito de ter uma função retornando mais de um valor. Por exemplo, divmod(a,b) retorna uma tupla com o resultado inteira da divisão e o resto. Funções do usuário podem fazer o mesmo, inclusive retornando outra função, como veremos.
» divmod(10,3) ↳ (3, 1) » div, resto = divmod(10,3) » print(div) ↳ 3 » print(resto) ↳ 1 # Um exemplo de uma função que retorna uma sequência » def min_max(seq): » return min(seq), max(seq) » » seq = (23,45,23,78,1,23,0,-34) » min_max(seq) ↳ (-34, 78) » seq = {23,45,23,78,1,23,0,-34} » min_max(seq) ↳ (-34, 78) # funções com n argumentos » def imprima_tudo(*args): » print(args) » imprima_tudo(1,2, '3', True) ↳ (1, 2, '3', True) # sem * temos um erro » def imprima(args): » print(args) » imprima(1,2) ↳ --------------------------------------------------------------------------- TypeError: imprima() takes 1 positional argument but 2 were given
Função zip()
Uma função interna interessante e útil é zip()
. Ela recebe como argumentos duas ou mais sequências e as compacta em um objeto zip que é um iterador de tuplas, onde cada tupla contem um elemento de cada sequência usada como parâmetro. Ela retorna um iterador de tuplas, onde a i-ésima tupla contém o i-ésimo elemento de cada uma das sequências ou iteráveis fornecidas em seu argumento. Se as sequências não tem o mesmo comprimento o iterador retornado tem o comprimento da menor. Se nenhum argumento for fornecido ela retorna um iterador vazio. Com um único argumento iterável, ele retorna um iterador de tuplas de um elemento.
» seq1 = 'Blade' » seq2 = 'Runner' » zipado = zip(seq1, seq2) » print(zipado) ↳ <zip object at 0x7f27c9f77500> # use a função tuple() para visualizar o objeto zip » print(tuple(zipado)) ↳ (('B', 'R'), ('l', 'u'), ('a', 'n'), ('d', 'n'), ('e', 'e')) # usando a mesma variável já definida » for letra1, letra2 in zipado: » print(letra1, letra2) ↳ B R ↳ l u ↳ a n ↳ d n ↳ e e # um objeto zip pode ser passado como argumento na construção # de uma lista gerando uma lista de tuplas » s1 = [1, 2, 3] » s2 = ['a', 'b', 'c'] » list(zip(s1, s2)) ↳ [(1, 'a'), (2, 'b'), (3, 'c')] # várias sequências podem ser fornecidas » s1 = 'Margem' » s2 = 'direita' » s3 = 'do rio' » zip123 = zip(s1, s2, s3) » for a,b,c in zip123: » print(a, b, c) ↳ M d d ↳ a i o ↳ r r ↳ g e r ↳ e i i ↳ m t o
No útimo exemplo a sequência s2 tem maior comprimento que as demais. A letra final ‘a’ foi ignorada.
Suponha que desejamos analisar duas sequências e verificar se elas possuem elementos iguais em uma mesma posição. No exemplo abaixo fazemos este teste usando zip() e definindo uma função que retorna True se houver essa coincidência. Observe que a função é abandonada na ocorrência da primeira coincidência.
Pode ocorrer que precisamos saber qual é a posição desse (ou de vários elementos comuns). Para isso usamos enumerate()
. Ela tem a seguinte forma:
enumerate(iteravel, inicio=0)
onde iteravel é uma sequência ou qualquer objeto iterável. Ela retorna pares iteráveis contendo o elemento e sua posição, começando em início (com default 0) e o elemento da sequência.
# função que retorna True se houver coincidência de elementos (ou False se não houver) » def mesmo_elemento(t1, t2): » for i, j in zip(t1, t2): » if i == j: » return True » return False » t1 = [1,2,3,4,5,6,7,8,9] » t2 = [9,8,7,6,5,4,3,2,1] » mesmo_elemento(t1,t2) ↳ True # Para informar a posição da coincidência usamos enumerate » for index, element in enumerate('abc'): » print(index, element) ↳ 0 a ↳ 1 b ↳ 2 c » type(enumerate('abdc')) ↳ enumerate # Repetindo o exemplo anterior, queremos descobrir se duas sequências # possuem elementos comuns na mesma posição, e que posição é essa » def posicao_elemento(t1, t2): » ''' retorna dictionary com indice e elemento onde elemento de t1 é igual ao de t2 ''' » dict = {} » if len(t2) < len(t1): » (t1, t2) = (t2, t1) » for index, i in enumerate(t1): » if i == t2[index]: » dict[index] = i » return dict » t2 = [1,2,3,4,5,6,7,6,9] » t1 = [9,8,7,4,3,4,5,6,7,8,9,0,23,45] » posicao_elemento(t1,t2) ↳ {3: 4, 7: 6} » t1 = 'josefina' » t2 = 'gasolina cara' » posicao_elemento(t1,t2) ↳ {2: 's', 5: 'i', 6: 'n', 7: 'a'}
A linha if len(t2) < len(t1): (t1, t2) = (t2, t1)
garante que t2 tenha o maior comprimento. Caso contrário o teste i == t2[index]
poderia poderia dar erro ao tentar obter elemento inexistente de t2.
Compreensão de Listas (List Comprehensions)
Suponha que queremos uma lista com os quadrados de todos os números de 0 até 10. Podemos conseguir isso usando um laço for:
» quadrados = [] » for i in range(11): » quadrados.append(i**2) » » quadrados ↳ [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
Há uma forma alternativa no Python para conseguir o mesmo resultado chamada compreensão de listas (list comprehensions).
Sua sintaxe básica é
[expressão(item) for item in lista if condição]
.
» quads = [i**2 for i in range(1, 11)] » quads ↳ [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
Essa forma permite que se escreva um código mais compacto, legível e eficiente (portanto de mais rápida execução).
A expressão pode ser uma função do usuário. No exemplo usamos a função já definida anteriormente para o cálculo de fatoriais:
» def fatorial(n): » if n <= 1: return 1 » else: return n*fatorial(n-1) » # exibindo os fatoriais de ímpares de 1 a 9 » fats = [fatorial(i) for i in [1, 3, 5, 7, 9]] » fats ↳ [1, 6, 120, 5040, 362880] # atuando sobre strings » palavras = ['Organização', 'Nações', 'Unidas'] » letras = [l[0] for l in palavras] » letras ↳ ['O', 'N', 'U'] » tamanho = [len(p) for p in palavras] » tamanho ↳ [11, 6, 6]
Uma ou mais condições pode ser incluída na lista a ser iterada.
[expressao(item) for item in lista if condição1 if condição2 ...]
No exemplo abaixo usamos i%2
, que é o resto da divisão de i por 2. Se esse resto for 0 o número é par.
# ex.: lista dos números pares de 0 até 10, exclusive # i%2 == 0 significa que o número é par » num = [i for i in range(10) if i%2==0 ] » print(num) ↳ [0, 2, 4, 6, 8] # um exemplo com strings: apenas as palavras com comprimento maior que 5 » palavras = ['casa', 'aleatório', 'rudimentar', 'longo'] » [p for p in palavras if len(p) > 5 ] ↳ ['aleatório', 'rudimentar'] # Várias condições podem ser impostas simultaneamente # São retornados os múltiplos de 2 e 3 simultaneamente, i.e. os múltiplos de 6. » print([i for i in range(50) if i%2==0 if i%3==0]) ↳ [0, 6, 12, 18, 24, 30, 36, 42, 48] # a expressão na lista pode conter 'if else': # a abaixo expressão retorna 'abacaxi' para números pares, # 'laranja' para múltiplos de 3 e 'caqui' para todos os demais » fruits = ['abacaxi' if i%2==0 else 'laranja' if i%3==0 else 'caqui' for i in range(10)] » print(fruits) ↳ ['abacaxi', 'caqui', 'abacaxi', 'laranja', 'abacaxi', 'caqui', 'abacaxi', 'caqui', 'abacaxi', 'laranja'] # As listas podem ser aninhadas. Abaixo a lista externa percorre letras, # a lista interna percorre números » matriz = [[i+j for i in 'abcd'] for j in '1234'] » matriz ↳ [['a1', 'b1', 'c1', 'd1'], ['a2', 'b2', 'c2', 'd2'], ['a3', 'b3', 'c3', 'd3'], ['a4', 'b4', 'c4', 'd4']]
Um teste pode ser negado com o operador lógico not (que inverte o booleano). Usamos também o método string.isalpha() que retorna True se string for formado apenas de caracteres (sem dígitos ou pontuações).
# teste not in # isalpha() retorna True se a string é composta de caracteres alfabéticos » vogais = {'a', 'e', 'i', 'o', 'u'} » texto = 'Aprenda todas as regras e transgrida algumas 1234.' » letras = set(texto.lower()) » consoantes = {letra for letra in letras if letra not in vogais if letra.isalpha()} » consoantes ↳ {'d', 'g', 'l', 'm', 'n', 'p', 'r', 's', 't'} # na expressão seguinte um set de tuplas é gerado {(i, j) for i in range(3, 5) for j in range(2)} ↳ {(3, 0), (3, 1), (4, 0), (4, 1)} » print([i+j for i in 'abcd' for j in 'efgh']) ↳ ['ae', 'af', 'ag', 'ah', 'be', 'bf', 'bg', 'bh', 'ce', 'cf', 'cg', 'ch', 'de', 'df', 'dg', 'dh'] » substantivo = ['pão', 'pé', 'carro', 'bolo', 'mato'] » adjetivo = ['pequeno', 'bonito', 'bom', 'caro'] » ['%s %s' % (s, a) for s in substantivo for a in adjetivo if s[0] == a[0]] ↳ ['pão pequeno', 'pé pequeno', 'carro caro', 'bolo bonito', 'bolo bom'] # Podemos calcular o produto escalar de 2 vetores » u = [1,3,4,5,6] » v = [-1,0,9,-3,2] » sum([a+b for a,b in zip(u,v)]) ↳ 26
No cálculo do produto escalar zip(u,v)
contém 5 pares que são somados formando uma lista de 5 elementos. A função sum(lista)
soma esses 5 elementos.
Compreensão com dicionários
Compreensão de listas podem ser aplicadas a dicionários, alterando tanto suas chaves como valores. Lembrando dic.items()
retorna uma tupla chave:valor do dicionário.
# uma compreensão para duplicar os valores em um dicionário » dic1 = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5} » duplo_dic1 = {k:v*2 for (k,v) in dic1.items()} » duplo_dic1 ↳ {'a': 2, 'b': 4, 'c': 6, 'd': 8, 'e': 10} # alterar o texto nas chaves, acrescentando prefixo R » R_dic1 = {'R'+k : v*2 for (k,v) in dic1.items()} » R_dic1 ↳ {'Ra': 2, 'Rb': 4, 'Rc': 6, 'Rd': 8, 'Re': 10} » s_dic = {l.upper(): l*3 for l in 'dna'} » print (s_dic) ↳ {'D': 'ddd', 'N': 'nnn', 'A': 'aaa'}
No exemplo seguinte queremos construir um dicionário onde a chave é um par entre 1 e 10, inclusive, e o valor é seu quadrado. Fazemos isso sem compreensão de lista e depois com.
# Obs. percorrer i = 1, ..., 5 e tomar seu dobro garante que usamos apenas os pares de 1 a 10 » dic_2 = {} » for i in range(1,6): » dic_2[i*2] = (i*2)**2 » dic_2 ↳ {2: 4, 4: 16, 6: 36, 8: 64, 10: 100} # a mesma construção, usando compreensão » dic_3 = {n:n**2 for n in range(1,11) if n%2 == 0} » dic_3 ↳ {2: 4, 4: 16, 6: 36, 8: 64, 10: 100} # o mesmo resultado será obtido com » dic_4 = {2*n:(2*n)**2 for n in range(1,6)} » dic_4 ↳ {2: 4, 4: 16, 6: 36, 8: 64, 10: 100} # Podemos usar compreensões para filtrar elementos de um dicionário » dic_4a = {k:v for (k,v) in dic_4.items() if v>36} » dic_4a ↳ {8: 64, 10: 100} » # selecionando apenas valores em um intervalo » dic_4b = {k:v for (k,v) in dic_4.items() if v > 16 if v < 100} » dic_4b ↳ {6: 36, 8: 64} # duas condições podem ser usadas » dic_4b = {k:v for (k,v) in dic_4.items() if v > 16 if v < 100} » dic_4b ↳ {6: 36, 8: 64} # duas condições, sobre chave e valor » dic_4c = {k:v for (k,v) in dic_4.items() if k > 5 if v < 90} » dic_4c ↳ {6: 36, 8: 64} # o valor é (im)par para chave (im)par » dic_par_impar = {i:('par' if i%2==0 else 'impar') for i in range(5)} » dic_par_impar ↳ {0: 'par', 1: 'impar', 2: 'par', 3: 'impar', 4: 'par'}
Algumas vezes pode ser útil usar zip()
para construir dicionários através de uma compreensão.
# Lists to represent keys and values » keys = [101, 201, 301, 401, 501] » values = ['inglês', 'francês', 'alemão', 'russo', 'espanhol'] # keys e values são colocados em um único iterável (um objeto zip) » dic_5 = { k:v for (k,v) in zip(keys, values)} » print(dic_5) ↳ {101: 'inglês', 201: 'francês', 301: 'alemão', 401: 'russo', 501: 'espanhol'} # observe que o iterável poderia ser dado diretamente como parâmetro do construtor » dic_6 = dict(zip(keys, values)) » print(dic_6) ↳ {101: 'inglês', 201: 'francês', 301: 'alemão', 401: 'russo', 501: 'espanhol'} # dicionários aninhados » dicionario = {i: {j: i*j for j in range(1, 6)} for i in range(2, 5)} » print(dicionario) ↳ {2: {1: 2, 2: 4, 3: 6, 4: 8, 5: 10}, 3: {1: 3, 2: 6, 3: 9, 4: 12, 5: 15}, 4: {1: 4, 2: 8, 3: 12, 4: 16, 5: 20}}
Nesse dicionário as chaves vão de 2 até 4 e seus valores são outros dicionários.
Compreensões de listas e de dicionários são formas elegantes e de fácil leitura. No entanto, se forem muito complexas elas podem tornar o código difícil de ler e de debugar (encontrar eventuais erros). Devemos nos lembrar que outras pessoas podem necessitar ler o nosso código, ou você mesmo, daqui a um tempo, quando dificilmente se lembrará do raciocínio que te levou à construção de bloco sofisticados e elegantes.
Função filter()
A função tem a forma de
filter(funcao, sequencia)
e constroi um iterador usando uma função booleana (que retorna True ou False) e uma sequência ou um iterável qualquer. Ela testa cada elemento da sequência usando a função e retorna apenas os elementos avaliados como True.
» idades = [5, 12, 17, 18, 24, 32] » def maior(x): » if x < 18: » return False » else: » return True » adultos = filter(maior, idades) » for x in adultos: » print(x) ↳ 18 ↳ 24 ↳ 32 # observe que a função acima poderia ser escrita simplesmente como » def maior(x): » return x ≥ 18
No próximo exemplo temos uma lista de dicionários. Cada entrada dessa lista é um dicionário contendo dados sobre um animal. O código define uma função pesquisa que recebe essa lista e procura quais de suas entradas contém algum valor com o substring busca.
» bicharada = [ » {'nome': 'Asdrubal', 'especie': 'tubarão', 'peso': '290', 'habitat': 'oceano'}, » {'nome': 'Ana Lee', 'especie': 'caranquejo', 'peso': '1.2', 'habitat': 'oceano'}, » {'nome': 'Raul', 'especie': 'urso', 'peso': '180', 'habitat': 'floresta'}, » {'nome': 'Joana', 'especie': 'raposa', 'peso': '21', 'habitat': 'floresta'}, » {'nome': 'Omar Lee', 'especie': 'golfinho', 'peso': '120', 'habitat': 'oceano'}, » {'nome': 'Tulio', 'especie': 'rato', 'peso': '1.4', 'habitat': 'doméstico'} » ] » def pesquisa(lista, busca): » def meu_iterador(x): » for v in x.values(): » if busca in v: » return True » return False » return filter(meu_iterador, lista) » lista_filtrada = pesquisa(bicharada, 'tuba') » for t in lista_filtrada: » print(t) ↳ {'nome': 'Asdrubal', 'especie': 'tubarão', 'peso': '290', 'habitat': 'oceano'} » lista_filtrada = pesquisa(bicharada, 'Lee') » for t in lista_filtrada: » print(t) ↳ {'nome': 'Ana Lee', 'especie': 'caranquejo', 'peso': '1.2', 'habitat': 'oceano'} ↳ {'nome': 'Omar Lee', 'especie': 'golfinho', 'peso': '120', 'habitat': 'oceano'}
Sugestão: altere o código acima para encontrar parte de um valor dentro de um campo especificado. Encontre o animal cujo habitat contém a substring ‘ocea’.
Iteradores (iterators)
No Python um iterador é um objeto que contém um número contável de elementos que podem ser iterados, ou seja, que podem ser acessados e lidos um de cada vez. Além dos laços for e das compreensões de listas e sequências no Python podemos utilizar iteradores para percorrer sequências. Eles pode ser construídos com a função
nome_iterador = iter(sequencia, marcador)
.
O parâmetro marcador é opcional e …..
O iterador tem o método _next()_ que fornece o próximo elemento. Uma exceção StopIteration é lançada no final, quando todos os elementos foram percorridos. O iterador é esgotado e, portanto, só pode ser percorrido uma vez.
Exemplos de uso estão no código abaixo. Lista são convertidas em iteradores, que são percorridos com next().
Se a iteração não é interrompida antes do fim um erro é lançado. Um erro é gerado no final e sua captura é usada para interromper o laço.
# Uma lista é convertida em um iterador lista = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] it = iter(lista) for k in range(len(lista)): print(next(it), end=' ') a b c d e f g h # queremos separar números positivos e negativos de uma lista # o erro no final da iteração é usado para interromper o laço » original = [1,6,-8,-3,0, -2, 9, 76, -45] » positivos = [] » negativos = [] » t = iter(original) » try: » while True: » x = next(t) » if x >= 0: » positivos.append(x) » else: » negativos.append(x) » except StopIteration: » print('São positivos:' , positivos, '\nSão negativos:' , negativos) ↳ São positivos: [1, 6, 0, 9, 76] ↳ São negativos: [-8, -3, -2, -45]
Embora a mesma funcionalidade possa ser conseguida de formas diferentes a transformação de um objeto iterável em um iterador é bastante útil para se escrever classes e métodos definidos pelo programador, como veremos.
Funções Lambda
Funções são boas formas de escrever código de fácil reutilização. No entanto, algumas vezes precisamos de definir um operador de forma compacta e que será utilizado apenas naquele ponto do código. As funções lambda (ou funções anônimas) permitem a criação de funções (que sequer recebem um nome) mas agem da forma desejada sobre seus argumentos.
Funções lambda tem uma sintaxe concisa:
lambda <arg1, ..., argn> : < expressão >
Elas só podem conter uma única expressão, nenhuma declaração, deve ser escrita em linha única e não comportam anotações. São exemplos simples de funções lambda:
# uma função bem simples é a identidade. # a definição usual seria » def id(x): » return x # usando função lambda » i = lambda x: x » i(9) ↳ 9 # a função não precisa ser associada a uma variável » (lambda x: abs(x))(-9) ↳ 9 # outros ex. Soma e multiplicação » x = lambda a, b : a + b » x(5,7) ↳ 12 # múltiplos argumentos não são envoltos em parênteses » exp = lambda x,y : x**y » exp(2,3) ↳ 8 » mix = lambda x,y,z : (x**y)/z » mix(3,4,5) ↳ 16.2 # qualquer tipo de objeto pode ser passado como argumento # no exemplo uma tupla é passada » u = (4,7) » (lambda x: x[0]*x[1])(u) ↳ 28 # uma função lamba que age sobre strings # .title torna o primeiro caracter maiúsculo » nome_autor = lambda nome, sobrenome: f'Autor: {nome.title()} {sobrenome.title()}' » nome_autor('richard','dawkins') ↳ 'Autor: Richard Dawkins'
Um exemplo de uso frequente consiste no uso de lambdas para fornecer um critério de ordenamento.
Vimos que a função sorted(sequencia, key) pode ordenar uma sequência de acordo com um critério dado em key. No caso abaixo a cada tupla é associado o produto de seus pares, e a ordenação é feita nessa métrica.
» p = [(3, 3), (4, 2), (2, 2), (5, 2), (1, 7)] » sorted(p, key=lambda x: x[0]*x[1]) ↳ [(2, 2), (1, 7), (4, 2), (3, 3), (5, 2)] # dados vetores no espaço, ordená-los em ordem crescente de módulo # a função lambda calcula o quadrado do módulo » v =[(1,5,3), (1,8,2), (7,8,9), (2,4,3), (2,2,-1)] » sorted(v, key=lambda x: x[0]**2+x[1]**2+x[2]**2) ↳ [(2, 2, -1), (2, 4, 3), (1, 5, 3), (1, 8, 2), (7, 8, 9)]
No exemplo seguinte definimos a função vezes_n
que recebe o argumento n e opera sobre ele com a função lambda lambda a : a * n
. Essa última, por sua vez, recebe outro argumento, no caso a. O exemplo também ilustra o fato de que uma função é um objeto e pode ser atribuída à uma variável.
# queremos uma função que multiplica seu argumento por um número especificado n » # n pode ser visto como um parâmetro » def vezes_n(n): » return lambda a : a * n » funcao_duplicar = vezes_n(2) # n = 2 » funcao_triplicar = vezes_n(3) # n = 3 » funcao_x1000 = vezes_n(1000) # n = 1000 » funcao_duplicar(23) # n = 2, a = 23 ↳ 46 » funcao_triplicar(15) # n = 3, a = 15 ↳ 45 » funcao_x1000(12.345) # n = 1000, a = 12.345 ↳ 12345.0
A minha_funcao abaixo é uma função lambda com dois argumentos sendo um deles outra função. No primeiro caso 2 + 2*10 = 22. No segundo caso 4 + (4)**3 -6 = 62.
» minha_funcao = lambda x, f: x + f(x) » minha_funcao(2, lambda x: x*10 ) # aqui f(x) = x*10 ↳ 22 » minha_funcao(4, lambda x: x**3-6) # aqui f(x) = x**6 - 6 ↳ 62
Função map()
Lambdas são muito usadas junto com a função
map()
que tem a seguinte assinatura:
map(funcao, iteravel1, ..., iteraveln)
.
Os dois argumentos são obrigatórios. A função percorre os iteráveis fornecidas usando a função especificada. Essa função deve usar um elemento de cada iterável. Ela usa um algoritmo otimizado para realizar sua transformação, o que a torna mais eficiente e rápida do que laços usuais do Python.
Ela retorna um objeto iterável map que pode ser convertido em lista com list(). Alguns exemplos:
# a operação abaixo concatena duas strings » def concatena(a, b): » return (a + ' ' + b) » iter1 = ('banana', 'laranja', 'uva') » iter2 = ('nanica', 'bahia', 'syrah') » x = map(concatena, iter1, iter2) # para ver o resultado podemos percorrer a iterável gerada # cada i no laço é uma única string (como 'banana nanica') » for i in x: » print(i) ↳ banana nanica ↳ laranja bahia ↳ uva syrah # a funcão pow(x,y) retorna x^y ou xy # como pow age com 2 argumentos, duas sequências devem ser dadas em map » y = map(pow, [6,7,8],[3,2,1]) » for i in y: » print(i, end=' - ') ↳ 216 - 49 - 8 - # a função pode ser uma lambda # duplicar cada elemento da lista » lista = [10, 25, 17, 9, 30, -5] » lista_2 = map(lambda n : n*2, lista) # para exibir a sequência retornada podemos transformá-la em uma lista » list(lista_2) ↳ [20, 50, 34, 18, 60, -10]
O uso de funções lambda pode tornar mais compacto o uso de map.
# para retornar uma lista de quadrados » def quadrado(n): » return n**2 » numeros = [1, 2, 3, 4, 5] » quadrados = map(quadrado, numeros) » list(quadrados) ↳ [1, 4, 9, 16, 25] # o mesmo resultado pode ser conseguido usando lambdas » list(map(lambda x:x**2, range(1,6))) ↳ [1, 4, 9, 16, 25] # abs() é função interna, que retorna valor absoluto » nums = [-5, -3, -1, 0, 1, 3, 5] » absolutos = list(map(abs, nums)) » absolutos ↳ [5, 3, 1, 0, 1, 3, 5] # somar e multiplicar com 3 listas » list(map(lambda i, j, k: i+j*k, [2, 4], [1, 3], [7, 8])) ↳ [9, 28] # strip() remove string dados nas extremidades da string » traco = ['---12356.876-', '-casa-da-vó---', '-mil-', '---'] » list(map(lambda s: s.strip("-"), traco)) ↳ ['12356.876', 'casa-da-vó', 'mil', ''] # função recebe um número e retorna tuplas de 3 elementos » def pot_1_2_3(x): » return x, x ** 2, x ** 3 » numeros = [1, 2, 3, 4] » list(map(pot_1_2_3, numeros)) ↳ [(1, 1, 1), (2, 4, 8), (3, 9, 27), (4, 16, 64)] # a mesma coisa usando lambda » list(map(lambda x: (x, x**2, x**3), numeros)) ↳ [(1, 1, 1), (2, 4, 8), (3, 9, 27), (4, 16, 64)]
Em muitos casos uma compreensão de lista faz o mesmo que uma iteração via map(). No entanto é útil conhecer a função não apenas para poder ler e compreender código escrito por outras pessoas mas também para eventuais situações onde ela pode ser mais simples ou mais eficaz.
Bibliografia
Consulte a bibliografia no final do primeiro artigo dessa série.
Lembra FORTRAN, no sec. XX. Claro, muito mais recurso. Gostei
FORTRAN é bastante usado ainda hoje e continua em desenvolvimento. Python é uma linguagem mais moderna de mais “alto nível”, no sentido em que entrega para o programador uma interface mais simples. O programador acaba escrevendo menos linhas para fazer a mesa tarefa. Acredito que é mais fácil aprender python que fortran.