Módulo 4 - Programação funcional

functools: reduce e partial

9 min de leitura · por Cesar Gargiulo, revisado pela equipe ValorFinal e GuardiaSec · Atualizado em 01/07/2026

O que você vai aprender

  • Acumular um iterável num único valor com reduce.
  • Saber quando reduce é melhor que um laço ou uma função pronta.
  • Fixar argumentos de uma função com partial.
  • Criar versões especializadas de funções sem repetição.

reduce: de um iterável a um valor

O reduce, do módulo functools, resume um iterável a um único valor. Ele recebe uma função de dois argumentos e vai aplicando essa função de forma acumulada: pega os dois primeiros itens, combina; pega o resultado e o próximo item, combina; e assim por diante até sobrar um valor. Multiplicar todos os números de uma lista, por exemplo, é reduzir a lista com a operação de multiplicação. É a terceira operação clássica ao lado de map e filter: onde map transforma e filter seleciona, reduce acumula.

from functools import reduce

numeros = [1, 2, 3, 4, 5]

# Produto de todos os itens: nao ha funcao pronta para isso.
produto = reduce(lambda acumulado, item: acumulado * item, numeros)
print(produto)  # 120

# Com valor inicial (comeca em 100):
soma_com_base = reduce(lambda a, b: a + b, numeros, 100)
print(soma_com_base)  # 115

reduce combina os itens par a par até um valor; aceita um valor inicial opcional.

Uma ressalva importante: nem tudo merece reduce. Para somar, o sum já existe e é mais claro; para o maior, o max; para juntar textos, o método join. Nesses casos, usar reduce só deixa o código mais difícil de ler. O reduce vale a pena quando a acumulação é incomum e não tem uma função pronta, como o produto acima ou uma combinação personalizada. A regra é preferir a ferramenta específica quando ela existe e reservar o reduce para o que ela não cobre.

partial: fixar argumentos de uma função

O partial cria uma função nova a partir de outra, fixando alguns argumentos. Suponha uma função de potência que recebe base e expoente. Se você usa muito o expoente 2, pode criar com partial uma função quadrado que já tem o expoente fixado, e só passa a base. É a aplicação parcial: você congela parte dos parâmetros e obtém uma versão especializada, sem reescrever a lógica. Isso evita repetição e deixa o uso mais direto, além de gerar funções sob medida para passar a map e outras.

from functools import partial

def potencia(base: float, expoente: float) -> float:
    return base ** expoente

# Fixa o expoente em 2: nasce uma funcao quadrado.
quadrado = partial(potencia, expoente=2)
cubo = partial(potencia, expoente=3)

print(quadrado(5))  # 25.0
print(cubo(2))      # 8.0

# Util para especializar funcoes passadas a map:
bases = [1, 2, 3, 4]
print(list(map(quadrado, bases)))  # [1, 4, 9, 16]

partial fixa o expoente e cria quadrado e cubo a partir de potencia, sem repetir código.

Combinando as ferramentas

As ferramentas do functools se combinam com o restante do estilo funcional. Você pode usar partial para preparar uma função especializada e passá-la a map, ou compor reduce com uma operação vinda de partial. O importante é lembrar que essas ferramentas existem para clareza, não para exibição. Um laço simples e explícito às vezes comunica melhor que um reduce engenhoso. Escolha a forma que a próxima pessoa a ler o código, incluindo você daqui a seis meses, vai entender mais rápido.

OperaçãoMelhor ferramenta
Somar todos os itenssum, não reduce
Maior ou menor itemmax ou min, não reduce
Juntar textosmétodo join, não reduce
Produto ou acumulação incomumreduce
Fixar um argumento sempre igualpartial

Prefira a ferramenta específica quando existe; reserve reduce para o incomum.

Com funções puras, map, filter, reduce e partial, você já tem um bom vocabulário funcional. Falta uma peça poderosa que também vive no functools e resolve um problema de desempenho de forma elegante: a memoização, que guarda resultados de chamadas para não recalcular. É o assunto da próxima aula, com o lru_cache, um decorador que acelera funções puras caras trocando um pouco de memória por muito tempo.

Teste rápido

O que o partial faz ao receber uma função e alguns argumentos?

Perguntas frequentes

Por que preferir sum a reduce para somar uma lista?
Porque sum é mais legível e direto: quem lê entende na hora que se está somando. Um reduce com uma soma exige decifrar a operação acumulada. A regra prática é usar a ferramenta específica quando ela existe, e o reduce só quando a acumulação não tem função pronta, como um produto.
reduce precisa de um valor inicial?
Não obrigatoriamente. Sem valor inicial, ele começa pelos dois primeiros itens do iterável. Com um valor inicial, passado como terceiro argumento, ele começa desse valor e combina com o primeiro item. O valor inicial também evita erro quando o iterável pode estar vazio, servindo de resultado padrão.
O que acontece se eu passar reduce sobre uma lista vazia?
Sem valor inicial, o reduce levanta erro numa sequência vazia, pois não há o que combinar. Com um valor inicial, ele devolve esse valor, sem erro. Por isso, quando o iterável pode estar vazio, fornecer um valor inicial é uma proteção simples e recomendada.
partial fixa só argumentos nomeados ou também os por posição?
Os dois. Você pode fixar argumentos por posição, na ordem, ou por nome, como expoente=2. Fixar por nome costuma ser mais claro e menos sujeito a confusão, especialmente quando a função tem vários parâmetros. O resultado é sempre uma nova função que espera os argumentos que sobraram.
Uma função criada com partial pode ser passada como qualquer função?
Sim. O resultado do partial é chamável como qualquer função, então serve de argumento para map, para sorted, para um callback ou onde uma função for esperada. É justamente um dos usos mais úteis: preparar uma versão com menos parâmetros para encaixar em uma interface que espera certa assinatura.
De onde importo reduce e partial?
Ambos do módulo functools, da biblioteca padrão: from functools import reduce, partial. Nada para instalar. O functools reúne ferramentas de ordem superior, isto é, que trabalham com funções, e é uma parada obrigatória de quem programa em estilo funcional no Python.

Fontes

Seu progresso fica salvo neste aparelho. Assinantes sincronizam entre os aparelhos.