Programação funcional em Python

Filter

O filter() é uma função que faz exactamente o que o seu nome dá a entender: filtra um objecto, sendo-lhe passada uma função de controlo e o objecto a filtrar. Consoante o retorno da função de controlo seja True ou False, o elemento do objecto é ou não incluído no objecto a ser retornado.

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

O filter neste caso verifica se o módulo da divisão de cada um dos elementos da lista por 2 dá resto 0 (ou seja, se é par ou não), e se der, retorna o elemento em questão. Neste caso, o retorno seria [2, 4, 6].

Situações onde é possível usar o filter, e as respectivas alternativas

Quando necessitamos de tirar todos os números pares de uma lista

filter(lambda x: x%2, lista) #sendo lista uma lista de inteiros -> [1, 2, 3]

Mais uma vez, uma boa alternativa seria o uso de listas por compreensão:

[x for x in lista if x%2]

Ou então um ciclo for:

novaLista = []
for x in lista:
  if x%2:
    novaLista.append(x)

Reduce

O reduce() é uma função que recebe uma função de controlo e o objecto iterável a reduzir. A função de controlo recebe dois argumentos: o que retornou na iteração anterior e o elemento actual do objecto. Opcionalmente, pode receber um terceiro argumento que vai ser passado à função de controlo na primeira iteração como o retorno da iteração anterior. No caso do terceiro argumento não ser passado, é utilizado o primeiro elemento do objecto iterável.

Exemplo: reduce(lambda x, y: x+y, [0, 1, 2, 3, 4, 5, 6, 7, 8])

Isto é equivalente a fazer 0+1+2+3+4+5+7+8 (o zero poderia ser outro valor, se tivesse passado o terceiro argumento), ou seja, a soma de todos os números até 8. O reduce neste exemplo irá retornar 36.

Situações onde é possível usar o reduce, e as respectivas alternativas

Calcular um factorial (neste caso, 9!):

reduce(lambda x, y: x*y, range(1, 10),1)

(O 1 no terceiro argumento é opcional.)

Usando uma função recursiva:

def fact(x):
  if x > 1:
    return x*fact(x-1)
  else:
    return x

fact(9)

Usando um ciclo for:

y = 1
for x in range(1, 10):
  y *= x

Zip

O zip() é uma função que recebe n objectos iteráveis e gera uma lista de tuplas. Cada tupla é composta pelos elementos de cada um dos objectos daquela iteração. A lista contem x tuplas de n elementos, sendo x = min(len(objecto1), len(objecto2), ..., len(objecton)) e n o número de objectos iteráveis passados ao zip.

Exemplo: zip([1, 2], [‘a’, ‘b’, ‘c’], [‘A’, ‘B’, ‘C’, ‘D’])

Neste exemplo, o zip retorna [(1, ‘a’, ‘A’), (2, ‘b’, ‘B’)].

Uma alternativa ao zip

Aqui fica uma função que replica o comportamento do zip que recebe uma lista com todos os objectos a iterar:

def zipper(x):
  returns = []
  size = min([len(y) for y in x])
  while size > 0:
    returns.append(tuple([y[size- 1] for y in x]))
    size -= 1
  return returns[::-1]

Publicado na edição 23 (PDF) da Revista PROGRAMAR.