300x250 AD TOP

Blogger news

AD (728x90)

Tecnologia do Blogger.

Colaboradores

Seguidores

Postagens populares

Tagged under: , ,

Programação Funcional - Python







O objetivo desse post é apresentar da forma simples e fácil de algumas das características do paradigma funcional aplicado na linguagem de programação Python. Como existem inúmeras literaturas na web falando sobre o que séria programação funcional e a sua diferença em relação a outros paradigmas optei por focar nas seguinte característica:

  • Expressão lambda
  • Funções de alta ordem: map(), filter(), reduce() e zip()

Importante: O aspecto funcional de Python permite escrever código compacto e eventualmente mais rápido, por outro lado corre-se o risco de deixar o código obscuro e de manutenção mais complicada.

permite escrever funções anônimas/sem-nome usando apenas uma linha de código.

Sintaxe:

lambda [ var1, var2, ..., varN ]: expr -> expr_ret

Onde var1, var2, ..., varN são variáveis que representam o argumento da função e expr é qualquer expressão válida em Python envolvendo essas variáveis.O resultado é uma nova expressão expr_ret.
Um exemplo trivial de lamba é a função identidade, que retorna o próprio elemento. Um exemplo prático de lambda é uma função que recebe dois valores (x e y) e retorna a soma desses elementos.

Exemplos:

Função identidade.
lambda x: x
Resultado: <function <lambda> at 0x1e3630>
Soma de dois valores.
lambda x, y: x+y
Resultado:<function <lambda> at 0x1e3670>
Note que o resultado é uma expressão do tipo lambda. Mas como posso obter algo útil, por exemplo, calcular 1+2 com lambda?

(lambda x, y: x+y)(1,2)
Resultado: 3

Esta forma de expressar um função é conhecida como função anonima, visto que a função não recebe um nome especifico pra ela.Agora caso queira dar um nome para ajudar a "lembrar" uma expressão lambda é necessário apenas guardá-la em uma variável.

identidade = lambda x: x
identidade('Python')
Resultado'Python'
soma = lambda x, y: x+y
soma(1, 2)
Resultado:3
Aparentemente lambda sozinho não tem muita graça ou utilidade, mas nas seções que se seguem faremos melhor uso dela. O importante é ter em mente que uma expressão lambda pode responder igual a qualquer função em Python.

Mapeamento - Map

O mapeamento consiste em aplicar uma função a todos os itens de uma sequência, gerando outra lista contendo os resultados e com o mesmo tamanho da lista inicial.

A forma mais simples de se usar o map é aplicando uma função função uma sequência seq, o resultado é sempre uma lista cujo os elementos são obtidos aplicando-se individualmente cada elemento de seq a função func. Ao mapear-se uma lista com None retorna-se os elementos originais da sequência.

Sintaxe:
map(funcão ou None, seq) ->lista

Exemplos:

map(None, [1, 3, 5])
resultado: [1, 3, 5]

map(abs, [-1, -2, -3])
Resultado: [1, 2, 3]

map(str, [2, 4, 6])
Resultado: ['2', '4', '6']

map(hex, (10, 11, 12))
Resulado: ['0xa', '0xb', '0xc']

Um exemplo mais interessante com uso da expressão lambda.
map(lambda x: x*x*x, [1, 2, 3, 4])
Resultado: [1, 8, 27, 64]

Forma Completa de Map

A forma completa de map admite uma função func (ou None) e um conjunto de sequencias (seq1, seq2, ..., seqN) como parâmetros.
Sintaxe:
map(func ou None, seq1, seq2, ..., seqN) ->lista

Atribuindo-se None ao map este retorna sempre uma tupla de N elementos que são os elementos cuja ordem deles é a ordem das sequencias até o tamanho da maior lista, índices maiores que as sequências são retornados como None.
Exemplos:
map(None, [135], [246])
[(1, 2), (3, 4), (5, 6)]
map(None, [1, 3, 5], [2, 4, 6, 8, 10])
[(1, 2), (3, 4), (5, 6), (None, 8), (None, 10)]
Fica fácil entender que se oferecermos ao map três listas é necessário então que a função aceite três variáveis como parâmetro. As seqüencias menoresque M são automaticamente preenchidas com o valor None e isso pode ser um inconveniente caso se tente aplicar a uma função que espera valores numéricos, pois None nunca é tratado como um valor numérico.

Exemplos:
map(lambda xyx*y, [135], [246])
[2, 12, 30]
map(lambda a, b, x: a*x+b, [1, 3, 5], [2, 4, 8], [0, 0, 0])
[2, 4, 8]

Redução – reduce

Redução significa aplicar uma função que recebe dois parâmetros, nos dois primeiros elementos de uma sequência, aplicar novamente a função usando como parâmetros o resultado do primeiro par e o terceiro elemento, seguindo assim até o final da sequência. O resultado final da redução é apenas um elemento.

A função reduce aplica acumuladamente os itens de uma sequência de entrada seq (da esquerda para a direita) a uma função func de dois parâmetros até reduzir esse cálculo a um único valor de resposta. Opcionalmente pode-se atribuir um valor inicial como parâmetro.

Sintaxe:
reduce(func, seq[, inicial]) -> valor
Exemplos:
reduce(lambda x, y: x+y, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
Resultado:55

reduce(lambda x, y: x+y, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 100)
Resultado:155

A função reduce() também pode ser usada para calcular fatorial:
fatorial = lambda n: reduce(lambda x, y: x*y, range(1, n))

Filtragem - filter

Na filtragem, uma função é aplicada em todos os itens de uma sequência, se a função retornar um valor que seja avaliado como verdadeiro, o item original fará parte da sequência resultante.

A função filter retorna uma sequência seq_ret cujos valores são os elementos da sequência de entrada seq que respeitam o seguinte critério: se a função for None os elementos que são verdadeiros são adicionados, caso uma função func esteja definida o valor de retorno da função é utilizado como valor verdade e apenas esses elementos vão fazer parte da sequência de retorno.

Sintaxe:
filter(func ou None, seq) -> seq_ret

A sequência seq_ret tem sempre o mesmo tipo de seq.

Exemplos:

filter(None, [0, 1, 2, None, 2>1, 'ola'])
Resultado:[1, 2, True, 'ola']
filter(lambda x: x > 3, [0, 1, 2, 3, 4, 5])
Resultado:[4, 5]

filter(lambda s: s > 'a', 'python r0cks!')
Resultado:'pythonrcks'

filter(lambda x: x % 2, [1, 2, 3, 4, 5, 6, 7])

Transposição - Zip

Transposição é construir uma série de sequências a partir de outra série de sequências, aonde a primeira nova sequência contém o primeiro elemento de cada sequência original, a segunda nova sequência contém o segundo elemento de cada sequência original, até que alguma das sequências originais acabe.

A função zip retorna uma sequência seq_ret cujos elementos são tuplas resultantes de cada um dos elementos de uma ou mais sequências de entradaseq1, seq2, ..., seqN. A sequência resultante é sempre truncada ao tamanho da menor sequência apresentada.

Sintaxe:
zip(seq1, seq2, ..., seqN) -> seq_ret

O valor de m é o comprimento da menor lista em seq.
Exemplos:

zip([1, 3, 5], [2, 4, 6])
Resultado: [(1, 2), (3, 4), (5, 6)]
zip([1, 3, 5], [2, 4, 6, 8, 10])
Resultado:[(1, 2), (3, 4), (5, 6)]





0 comentários:

Postar um comentário