Pular para o conteúdo principal

Python reduce(): Um guia completo

Aprenda quando e como usar o reduce() do Python. Tem exemplos práticos e as melhores práticas.
Atualizado 28 de out. de 2025  · 11 min lido

A função ` reduce() ` da biblioteca Python vem do mundo da programação funcional. Programação funcional (FP) é um jeito de programar em que os programas criam resultados aplicando funções a dados que não mudam.

Um padrão comum nesse estilo é o “fold”, que transforma uma sequência em um único resultado. Por exemplo, dobrando a lista de números [2, 4, 5, 3] sob a adição 14 através de etapas sucessivas: [2, 4, 5, 3] → [6, 5, 3] → [11, 3] → 14.

reduce() generaliza essa ideia. Ele aplica uma operação binária em um iterável até que só o resultado fique.

Neste artigo, explorarei os principais elementos do Python ( reduce() ) e darei alguns exemplos práticos. Se você precisa dar uma repassada nos conceitos básicos do Python, recomendo dar uma olhada nesses recursos:

História

Python inclui outras funções de programação funcional em Python, como map() e filter().

Construções funcionais como map() e filter() estavam no Python 1.0. Guido van Rossum não gostava deles, apontando que reduce() era difícil de analisar, e que um loop for é quase sempre mais legível.  No Python 3.0, seguindo o PEP 3100, os desenvolvedores tiraram o ` reduce() ` como um built-in e colocaram ele no módulo ` functools `. Essa mudança para functools basicamente rebaixou o programa para o status de uma ferramenta de nicho.

Por que usar reduce()?

Na maioria das vezes, acho que provavelmente é melhor usar um loop ou um loop interno. Mas, o reduce() ainda é uma boa opção em alguns casos.

  • Funcionam como pipelines. Faça uma série de transformações (que podem ser dinâmicas) de um jeito bem organizado.
  • Dobras algébricas. Use para operações que têm valores de identidade naturais, como união de conjuntos com o conjunto vazio ou operações de máscara de bits com zero.
  • Dobragem personalizada sem integração. Defina sua própria fusão de um jeito específico para o domínio quando não tiver nenhuma integrada.
  • Acumuladores estruturados. Programa várias partes do estado ao mesmo tempo dentro de uma função acumuladora personalizada.

Como funciona a função reduce() do Python

Vamos ver como funciona o site reduce().

A assinatura da função básica de reduce() é

functools.reduce(function, iterable, [initializer])

A função reduce() aceita dois argumentos obrigatórios e um terceiro opcional.

  • function: uma função binária que diz como juntar dois elementos,
  • iterable: a sequência ou iterável a ser reduzida, como uma lista ou tupla, initializer(opcional): um valor inicial para semear a função.

Exemplo passo a passo:

  •  [1, 3, 2, 7] → [4, 2, 7].
  • [4, 2, 7] → [6, 7].
  • [6, 7] → [13].

O resultado final é 13.

Exemplos simples de reduce()

Os exemplos a seguir mostram como usar o reduce().

from functools import reduce

numbers = [2, 4, 6]
product = reduce(lambda x, y: x * y, numbers)  # ((2 x 4) x 6) = 8 x 6 = 48
min_value = reduce(lambda x, y: x if x < y else y, numbers) # 2

words = ['dog', 'cat', 'tree', 'pony']
str_concat = reduce(lambda x, y: x + y, words)  # "dogcattreepony"

Inicializador

Sem um inicializador, reduce() pega o primeiro elemento do iterável como seu valor inicial. Se o iterável estiver vazio, reduce() lança uma exceção TypeError. Para deixar o código mais robusto, use um inicializador para definir o que fazer quando não tiver nada na entrada.

from functools import reduce

words = []
# Error: reduce() of empty iterable with no initial value
str_concat = reduce(lambda x, y: x + y, words)

# Correct: use empty string initializer
str_concat = reduce(lambda x, y: x + y, words, "")

Os inicializadores também geram um resultado com um contêiner vazio. Por exemplo, você pode juntar palavras numa lista simples de caracteres. 

from functools import reduce

words = ['reduce', 'is', 'fun']
chars_list = reduce(lambda acc, word: acc + list(word), words, [])
print(chars_list)  # ['r', 'e', 'd', 'u', 'c', 'e', 'i', 's', 'f', 'u', 'n']

Pra explorar mais o Python e a manipulação de dados, aqui estão algumas opções que eu recomendo.

Definindo o redutor

Até agora, usamos funções lambda para definir o operador binário. 

Você também pode usar operadores do módulo operator.  O módulo operator tem versões de funções de operadores comuns e chamadas de método. Por exemplo, em vez de x + y, operator.add(x, y). Isso permite que você passe operadores pré-definidos (e eficientes) para um reduce() sem precisar escrever um lambda.

from functools import reduce
import operator as op

numbers = [2, 4, 6]
total = reduce(op.add, numbers, 0)  # instead of reduce(lambda x,y: x + y, numbers)

Uma terceira opção é escrever uma função personalizada. Essa é uma boa opção quando não tem um operador pré-definido ou a função é muito complicada para um lambda. 

Por exemplo, digamos que você queira tirar as duplicatas de uma lista, mas manter a ordem em que elas aparecem pela primeira vez. Você pode definir um redutor que acrescente um item a uma lista apenas se ele não tiver aparecido antes.  

from functools import reduce


items = ['the', 'wild', 'wild', 'world', 'is', 'the', 'wide', 'world', 'is', 'the', 'world']


def dedup(acc, x):
    if x not in acc:  # O(n) membership test
        acc.append(x)
    return acc




unique = reduce(dedup, items, [])  # ['the', 'wild', 'world', 'is', 'wide']

Para mais dicas sobre como eliminar duplicatas, dá uma olhada neste tutorial.

Desempenho do reduce() em Python

reduce() tem a ver com problemas de desempenho.

Sobrecarga da chamada de função

Python reduce() chama nossa função uma vez para cada elemento. Em uma lista com um milhão de itens, isso significa um milhão de chamadas de função, cada uma das quais cria um quadro, lida com argumentos e atualiza contagens de referência. Isso adiciona uma sobrecarga significativa.

Por outro lado, um built-in como sum faz uma única chamada para uma função C e faz um milhão de adições dentro do loop C. Essa diferença pode tornar as ordens de magnitude integradas mais rápidas.

Problemas de localidade do cache e eficiência da CPU

O Reduce também tem problemas com a localidade do cache e a eficiência da CPU.  

Uma CPU moderna consegue fazer vários bilhões de instruções por segundo, mas o acesso à RAM é bem mais lento. Pra compensar, as CPUs modernas têmcaches d e (L1, L2, L3) que guardam dados pra acesso rápido.

Esses caches usam dois padrões. 

  • Localidade temporal Os dados usados recentemente provavelmente serão usados de novo. 
  • Localidade espacial Os dados próximos a um endereço usado recentemente provavelmente serão usados em breve.

Por outro lado, cada etapa de uma busca por ponteiros ( reduce() ) envolve a busca por ponteiros para encontrar o próximo elemento e chamadas de funções Python, o que quebra a localidade e atrasa a CPU. Funções embutidas e vetorizadas evitam esse problema ao executar loops C restritos.

Pra dar uma repassada sobre como escrever código Python eficiente e idiomático, dá uma olhada em:

Alternativas ao Python reduce()

Embutidos:

  • Código C otimizado. Os built-ins rodam seus loops em código C otimizado, não em Python. Isso evita a sobrecarga que o reduce() causa. Essa vantagem de velocidade aumenta com grandes entradas. 
  • Legibilidade. Os built-ins têm nomes descritivos (sum, min), então o que eles fazem é bem claro. Uma chamada para reduce() faz com que você analise a função que está sendo dobrada.

Loops:

  • Desempenho. Os loops geralmente são mais lentos do que os built-ins, mas mais rápidos do que um reduce().
  • Legibilidade. Assim como os built-ins, os loops geralmente são mais fáceis de ler do que um reduce(). Uma chamada para reduce() obriga você a analisar uma instrução funcional, enquanto um loop é mais Python.

itertools.accumulate()

A biblioteca Python itertools oferece um monte de iteradores eficientes, como count(), product() e combinations(). Uma função útil do itertools é itertools.accumulate(). Assim como reduce(), ele aplica uma função sobre um iterável. Mas, accumulate() guarda os valores intermediários do cálculo, não só o resultado final. 

Por exemplo,

import itertools, operator
from functools import reduce

list(itertools.accumulate([1, 2, 3, 4], initial=0)) # [0, 1, 3, 6, 10]
reduce(operator.add, [1, 2, 3, 4], 0) # 10

Acumular é útil quando você precisa de totais acumulados ou mínimos/máximos. Por exemplo, você pode querer saber a temperatura máxima mês a mês.

Erros comuns ao usar reduce()

Quando você usar o reduce(), fique atento às seguintes armadilhas.

  • Prefira alternativas mais simples, como built-ins ou loops. Guarde o site reduce() para quando você realmente precisar dele.
  • Lidar com iteráveis vazios. Sempre use um inicializador apropriado para evitar erros em entradas vazias.
  • Fica de olho nos problemas de memória. Não tente forçar o uso de um gerador de chaves ( reduce() ) em situações em que um gerador ou uma abordagem de streaming seriam mais eficientes.
  • Evite lambdas complicadas. Use as funções do módulo ` operator ` sempre que puder. Lambdas, principalmente com operações não associativas, podem prejudicar a clareza.
  • Prefira a clareza à esperteza.

Melhores práticas e diretrizes para reduce() em Python 

Como com qualquer ferramenta, tem as melhores práticas com o reduce(). Se você decidiu que reduce() é a ferramenta certa pra usar, aqui vão algumas dicas de como usá-la.

Primeiro, projete o redutor. 

  • Defina o contrato em uma frase. “Junte as chaves do dicionário somando as contagens por chave.”
  • Mantenha-o associativo, se possível. Isso permite que você paralelize e teste com mais facilidade.
  • Identifique o seu elemento de identidade e use-o como inicializador. Por exemplo, para a soma, a identidade é 0. Para min, é math.inf, e para set union, é set(). Isso mantém o código robusto e livre de TypeErrors.

Mantenha a simplicidade e a legibilidade

  • Uma operação simples. Sem efeitos colaterais.
  • Dê um nome que descreva bem o redutor.

Documento

  • Na string de documentação, anote o elemento de identidade e o comportamento de entrada vazia, a suposição de associatividade e a política de erros.

Teste

  • Testes unitários em casos extremos: iterável vazio, tipos mistos, valores extremos.
  • Testa a associatividade.

Monitorar o desempenho

  • Compare entradas pequenas e grandes. Compare benchmarks com funções internas e loops.
  • Se a velocidade é importante, pense em pré-processar, fazer em lotes e passar cálculos pesados para o NumPy ou pandas.

Aplicações avançadas e casos de uso reais para Python reduce()

Considerando as desvantagens, pode parecer que o reduce() não tem nenhum valor real. Pelo contrário, reduce() tem muitos casos de uso úteis. 

  • Processando estruturas aninhadas
  • Operações do tipo banco de dados
  • Pipelines de processamento de dados
  • Aplicativos MapReduce

Processando estruturas aninhadas

O Reduce oferece uma maneira simples de percorrer estruturas de dados aninhadas, como objetos JSON, dobrando uma sequência de chaves em pesquisas sucessivas.

import json
from functools import reduce
import operator

data = json.loads('''
{
  "user": {
    "id": "ABC123",
    "name": "Alice",
    "email": "alice@example.com",
    "profile": {
      "address": {
        "city": "San Francisco",
        "zip": "94103"
      },
      "age": 34,
      "skills": ["Python", "Data Science", "Machine Learning"]
    }
  }
}
''')

# Example lookups with reduce + operator.getitem
city = reduce(operator.getitem, ["user", "profile", "address", "city"], data)
print(city)  # "San Francisco"

user_id = reduce(operator.getitem, ["user", "id"], data)
print(user_id)  # "ABC123"

age = reduce(operator.getitem, ["user", "profile", "age"], data)
print(age)  # 34

Usar reduce() faz sentido aqui. O JSON está bem aninhado: user → profile → address → city. Em vez de encadear pesquisas manualmente, represente o caminho como uma lista de chaves. Depois, usa reduce(operator.getitem, path, data) para percorrê-lo. Isso mantém o código genérico, legível e reutilizável.

Pipelines de processamento de dados

O Reduce pode conduzir pipelines de processamento de dados, passando os dados por uma sequência de transformações. Cada função cuida de uma etapa, e o pipeline é o resultado de aplicá-las na ordem certa. Aqui está um pipeline de brinquedo que pré-processa uma sequência de texto antes de alimentá-la em um modelo de NLP. 

from functools import reduce
import re

# Define preprocessing steps
def strip_punctuation(s):
    return re.sub(r"[^\w\s]", "", s)

def to_lower(s):
    return s.lower()

def remove_stopwords(s):
    stops = {"the", "is", "a", "of"}
    return " ".join(word for word in s.split() if word not in stops)

def stem_words(s):
    # trivial "stemmer": cut off 'ing'
    return " ".join(word[:-3] if word.endswith("ing") else word for word in s.split())

pipeline = [
    strip_punctuation,
    to_lower,
    remove_stopwords,
    stem_words,
]

# Input data
text = "The quick brown fox is Jumping over a log."

# Apply pipeline with reduce
processed = reduce(lambda acc, f: f(acc), pipeline, text)
print(processed)  # quick brown fox jump over log

Tratamento de erros em aplicativos complexos

Vamos voltar ao exemplo JSON aninhado. Agora, a chamada direta para reduce(operator.getitem, …) gera uma exceção KeyError ou TypeError se uma chave estiver faltando ou se encontrar um objeto que não seja um dicionário. Para deixar o código mais seguro, crie uma função auxiliar que envolva operator.getitem em um bloco try/except e retorne um valor padrão quando ocorrer um erro.

Aqui está uma possibilidade para a função auxiliar.

def deep_get(data, keys, default=None):
    """Traverse nested dicts/lists safely with reduce."""
    try:
        return reduce(operator.getitem, keys, data)
    except (KeyError, IndexError, TypeError):
        return default

Agora, mude as pesquisas de exemplo para usar nossa nova função em vez de uma função desempacotada. reduce()

# Example lookups
city = deep_get(data, ["user", "profile", "address", "city"], default="Unknown City")
print(city)  # "San Francisco"

user_id = deep_get(data, ["user", "id"], default="N/A")
print(user_id)  # "ABC123"

age = deep_get(data, ["user", "profile", "age"], default="N/A")
print(age)  # 34

# Example with missing key
phone = deep_get(data, ["user", "profile", "phone"], default="No phone")
print(phone)  # "No phone"

Transformações de dados em várias etapas com map() e filter()

Você pode juntar o reduce() com outras ferramentas úteis, como map() e filter(), para criar transformações de dados em várias etapas.  Aqui está o nosso pipeline de pré-processamento de PNL anterior, escrito de forma funcional.

from functools import reduce
import re

# Define preprocessing steps
def strip_punctuation(s):
    return re.sub(r"[^\w\s]", "", s)

def to_lower(s):
    return " ".join(map(str.lower, s.split()))

def remove_stopwords(s):
    stops = {"the", "is", "a", "of"}
    return " ".join(filter(lambda w: w not in stops, s.split()))

def stem_words(s):
    # trivial "stemmer": cut off 'ing'
    return " ".join(map(lambda w: w[:-3] if w.endswith("ing") else w, s.split()))

# Pipeline of transformations
pipeline = [
    strip_punctuation,
    to_lower,
    remove_stopwords,
    stem_words,
]

# Input data
text = "The quick brown fox is Jumping over a log."

# Apply pipeline with reduce
processed = reduce(lambda acc, f: f(acc), pipeline, text)
print(processed)  # quick brown fox jump over log

As transformações são:

  • Tira a pontuação. “A rápida raposa marrom está pulando sobre um tronco.” → “A rápida raposa marrom está pulando sobre um tronco.”
  • Letras minúsculas

“A rápida raposa marrom está pulando sobre um tronco” → “a rápida raposa marrom está pulando sobre um tronco”

  • Tira as palavras irrelevantes. “A rápida raposa marrom está pulando sobre um tronco” → “rápida raposa marrom pulando sobre tronco”
  • Palavras-raiz

 “raposa marrom rápida pulando tronco” → “raposa marrom rápida pula tronco”

Para saber mais sobre programação funcional e vetorização, a gente recomenda esses artigos do DataCamp.

Integração com o ecossistema Python moderno

Pra usar bem o reduce(), é legal entender como ele se encaixa no ecossistema Python moderno. Vamos ver como ele se encaixa ao lado do NumPy e do pandas, como ele sustenta sistemas paralelos e distribuídos e como ele interage com ferramentas modernas, como analisadores estáticos. 

numpy e pandas

O NumPy e o pandas funcionam a partir de código C otimizado, então não duplique suas funcionalidades com reduce(). Mas, o reduce() é uma boa opção para pipelines com etapas dinâmicas. Por exemplo, você pode compor várias transformações NumPy em uma matriz.

from functools import reduce
import numpy as np

def standardize(x):
    return (x - x.mean()) / (x.std() + 1e-9)

def clip(x):
    return np.clip(x, 0, 1)

def log(x):
    return np.log1p(x)

x = np.array([1, 500, 40.5, 100, 250.45])
funcs = [standardize, clip, log]
y = reduce(lambda a, f: f(a), funcs, x)  # x is ndarray

Estruturas de computação paralela e distribuída

A redução é essencial para estruturas de computação paralela e distribuída. Esses sistemas funcionam dividindo um conjunto de dados em partições, processando essas partições em paralelo e, em seguida, combinando esses resultados parciais em uma única resposta. A etapa de “combinar” é a redução.

Para que a redução funcione corretamente em um cluster, certifique-se de que as seguintes condições sejam atendidas.

  • Associatividade. A operação deve dar o mesmo resultado, não importa como você agrupar. Isso permite que resultados parciais sejam combinados em qualquer ordem na rede.
  • Elemento de identidade. A operação precisa ter um inicializador que não mexa no resultado final. Isso garante a correção quando as partições estão vazias ou têm tamanhos diferentes. 

Se essas propriedades não forem mantidas, as reduções ficam lentas (porque não podem ser paralelizadas com segurança) ou incorretas (porque os resultados dependem da ordem de avaliação).

Esse processo precisa de uma operação associativa e uma identidade clara. Caso contrário, você vai acabar com um código lento ou resultados errados.

Ferramentas de análise estática

Um analisador estático (como mypy, Pyright, ruff ou bandit) é uma ferramenta que dá uma olhada no código sem precisar rodá-lo. Essas ferramentas detectam bugs, aplicam regras de estilo e verificam a correção dos tipos.

Os analisadores estáticos têm dificuldade com reduce(). No processo de dobragem, o tipo de acumulador pode ser diferente do tipo de elemento, e a inferência de tipo fica confusa. 

Dá uma olhada nesse código.

from functools import reduce

def add_chars(acc, word):
    acc.extend(word)   # extend adds each character of the string
    return acc

chars = reduce(add_chars, ["hi", "ok"], [])
print(chars)  # ['h', 'i', 'o', 'k']

Mesmo que esse código funcione bem, um analisador estático pode reclamar de algumas coisas.

  • O tipo de elemento do inicializador [] é meio confuso. 
  • Os analisadores podem presumir que os tipos acumulador e elemento são compatíveis.

Para deixar o código mais claro para humanos e analisadores, adicione dicas de tipo.

from functools import reduce
from typing import List

def add_chars(acc: List[str], word: str) -> List[str]:
    acc.extend(word)   # extend adds each character of the string
    return acc

chars: List[str] = reduce(add_chars, ["hi", "ok"], [])
print(chars)  # ['h', 'i', 'o', 'k']

Agora, o redutor mostra explicitamente

  • O acumulador é um List[str].
  • Cada elemento é um str.
  • O tipo de retorno é um objeto de retorno de tipo( list[str]).

Com essas dicas, os analisadores estáticos podem verificar o código com rigor. 

Conclusão

Reduce vem da programação funcional, onde juntar coleções em um único resultado é uma ideia central. Mesmo que não seja mais uma ferramenta de primeira classe no Python, ela ainda tem seu lugar. Quando você precisa de pipelines flexíveis, dobras personalizadas ou operações que não se encaixam perfeitamente nas funções existentes, o reduce() é uma ferramenta poderosa. Usado com cuidado, ele se integra perfeitamente ao ecossistema Python e continua sendo uma ferramenta prática nas situações certas.

Alguns links relacionados ao Python que podem ser úteis.

Perguntas frequentes sobre reduce() em Python

O que o reduce() faz?

Ele aplica várias vezes uma função de dois argumentos a um iterável para reduzir a um único resultado.

Onde está definido reduce()?

Antes da versão 3, era uma função integrada. Desde então, ele tá no módulo functools.

Que tipo de funções devo passar para o reduce()?

Funções simples, associativas e bem documentadas. Evite efeitos colaterais e lógica não associativa.

Como isso se compara ao itertools.accumulate()?

reduce() retorna apenas o resultado final, enquanto accumulate() mostra todos os resultados intermediários.

Quando devo usar um inicializador?

Use um inicializador quando o iterável puder estar vazio.

Tópicos

Os melhores cursos de Python

Programa

Fundamentos de dados Python

0 min
Aumente suas habilidades com dados, descubra como manipular e visualizar dados e aplique análises avançadas para tomar decisões orientadas por dados.
Ver detalhesRight Arrow
Iniciar curso
Ver maisRight Arrow
Relacionado

Tutorial

Tutorial da função range() do Python

Aprenda sobre a função range() do Python e o que ela pode fazer com a ajuda de exemplos.
Aditya Sharma's photo

Aditya Sharma

Tutorial

Tutorial de funções Python

Um tutorial sobre funções em Python que aborda como escrever funções, como chamá-las e muito mais!
Karlijn Willems's photo

Karlijn Willems

Tutorial

Tutorial do Python pandas: O guia definitivo para iniciantes

Você está pronto para começar sua jornada com os pandas? Aqui está um guia passo a passo sobre como você pode começar.
Vidhi Chugh's photo

Vidhi Chugh

Tutorial

Tutorial de compreensão de dicionário Python

Saiba tudo sobre a compreensão de dicionário do Python: como você pode usá-la para criar dicionários, substituir loops for (aninhados) ou funções lambda por map(), filter() e reduce(), ...!
Sejal Jaiswal's photo

Sejal Jaiswal

Tutorial

Funções Lambda em Python: Um guia para iniciantes

Aprenda sobre as funções lambda do Python, para que servem e quando usá-las. Inclui exemplos práticos e melhores práticas para uma implementação eficaz.
Mark Pedigo's photo

Mark Pedigo

Tutorial

Tutorial e exemplos de funções e métodos de listas Python

Aprenda sobre as funções e métodos da lista Python. Siga agora os exemplos de código para list() e outras funções e métodos Python!
Abid Ali Awan's photo

Abid Ali Awan

Ver maisVer mais