Programação funcional é um paradigma que trata a computação como uma avaliação de funções matemáticas. Tais funções podem ser aplicadas em sequências de dados (geralmente listas). São exemplos de linguagens funcionais: LISP, Scheme e Haskell (esta última influenciou o projeto do Python de forma marcante).
As operações básicas do paradigma funcional são implementadas no Python pelas funções builtin map()
, filter()
, reduce()
e zip()
.
No Python, lambda é uma função anônima composta apenas por expressões. As funções lambda podem ter apenas uma linha, e podem ser atribuídas a uma variável. Funções lambda são muito usadas em programação funcional.
Sintaxe:
lambda <lista de variáveis>: <expressões>
Exemplo:
# Amplitude de um vetor 3D
amp = lambda x, y, z: (x ** 2 + y ** 2 + z ** 2) ** .5
print amp(1, 1, 1)
print amp(3, 4, 5)
1.73205080757 7.07106781187
Funções lambda consomem menos recursos computacionais que as funções convencionais, porém são mais limitados.
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.
No Python, o mapeamento é implementado pela função map()
.
Exemplos:
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
# log na base 10
from math import log10
print map(log10, nums)
# Dividindo por 3
print map(lambda x: x / 3, nums)
[0.0, 0.3010299956639812, 0.47712125471966244, 0.6020599913279624, 0.6989700043360189, 0.7781512503836436, 0.8450980400142568, 0.9030899869919435, 0.9542425094393249, 1.0, 1.041392685158225, 1.0791812460476249] [0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4]
A função map()
sempre retorna uma lista.
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.
No Python, a filtragem é implementada pela função filter()
.
Exemplo:
# Selecionando apenas os ímpares
print filter(lambda x: x % 2, nums)
[1, 3, 5, 7, 9, 11]
A função filter()
aceita também funções lambda, além de funções convencionais.
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.
Exemplos de redução, que é implementada no Python pela função reduce()
:
nums = range(100)
# Soma com reduce (pode concatenar strings)
print reduce(lambda x, y: x + y, nums)
# Soma mais simples, mas só para números
print sum(nums)
4950 4950
A função reduce()
pode ser usada para calcular fatorial:
# Calcula o fatorial de n
def fat(n):
return reduce(lambda x, y: x * y, range(1, n))
print fat(6)
120
A partir da versão 2.6, o módulo math traz uma função que calcula fatorial chamada factorial().
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.
Exemplo de transposição, que é implementada no Python pela função zip()
:
# Uma lista com ('a', 1), ('b', 2), ...
from string import ascii_lowercase
print zip(ascii_lowercase, range(1, 100))
# Transposta de uma matriz
matriz = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print zip(*matriz)
[('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7), ('h', 8), ('i', 9), ('j', 10), ('k', 11), ('l', 12), ('m', 13), ('n', 14), ('o', 15), ('p', 16), ('q', 17), ('r', 18), ('s', 19), ('t', 20), ('u', 21), ('v', 22), ('w', 23), ('x', 24), ('y', 25), ('z', 26)] [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
A função zip()
sempre retorna uma lista de tuplas.
Em computação, List Comprehension é uma construção que equivale a uma notação matemática do tipo:
$$ S = \\{ x^{2} \forall \in \mathbb{N}, x \geq 20 \\} $$Ou seja, S é o conjunto formado por x ao quadrado para todo x no conjunto dos números naturais, se x for maior ou igual a 20.
Sintaxe:
lista = [ <expressão> for <referência> in <sequência> if <condição> ]
Exemplo:
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
# Eleve os ímpares ao quadrado
print [ x**2 for x in nums if x % 2 ]
[1, 9, 25, 49, 81, 121]
List Comprehension é mais eficiente do que usar as funções map()
e filter()
tanto em termos de uso de processador quanto em consumo de memória.
Generator Expression é uma expressão que se assemelha ao List Comprehension, porém funciona como um gerador.
Exemplo:
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
# Eleve os ímpares ao quadrado
gen = ( x**2 for x in nums if x % 2 )
# Mostra os resultados
for num in gen:
print num
1 9 25 49 81 121
Outro exemplo:
# Uma lista de tuplas (artista, faixa):
instrumentais = [('King Crimson', 'Fracture'),
('Metallica','Call of Ktulu'),
('Yes', 'Mood for a Day'),
('Pink Floyd', 'One of This Days'),
('Rush', 'YYZ')]
# Filtra e ordena apenas as faixas de artistas anteriores a letra N
print sorted(faixa[-1] + ' / ' + faixa[0]
for faixa in instrumentais if
faixa[0].upper() < 'N')
['Call of Ktulu / Metallica', 'Fracture / King Crimson']
Generator Expression usa menos recursos do que o List Comprehension equivalente, pois os itens são gerados um de cada vez, apenas quando necessário, economizando principalmente memória.