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.
Ouvir o resumo desta aula
Um recap de cerca de 2 minutos na voz do Valim, para ouvir no trânsito ou na academia.
Ler a transcrição do resumo
Resumo da aula: functools: reduce e partial.
Os objetivos desta aula. 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.
Veja o essencial, parte por parte.
reduce: de um iterável a um valor. reduce acumula um iterável inteiro num único valor, aplicando uma operação par a par.
partial: fixar argumentos de uma função. Você chama a mesma função sempre com um argumento igual: fixe-o com partial.
Combinando as ferramentas. As ferramentas do functools se combinam com o restante do estilo funcional.
Esse foi o resumo do essencial. Para se aprofundar, leia a aula completa e responda os exercícios.
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) # 115reduce 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ção | Melhor ferramenta |
|---|---|
| Somar todos os itens | sum, não reduce |
| Maior ou menor item | max ou min, não reduce |
| Juntar textos | método join, não reduce |
| Produto ou acumulação incomum | reduce |
| Fixar um argumento sempre igual | partial |
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.