Pular para o conteúdo
Editor

map(), filter() e reduce() em Python: funções de ordem superior

Intermediário25 min7 exercícios100 XP

Este tutorial foi traduzido do original em inglês.Read in EnglishLeer en españolЧитать на русскомอ่านภาษาไทยAvisar sobre um erro de tradução

0/7 exercícios

Imagine a linha de montagem de uma fábrica. A matéria-prima entra por uma ponta. Na primeira estação, cada peça é moldada. Na seguinte, as peças com defeito são retiradas. Na última estação, todas as peças boas são combinadas em um único produto final.

O Python tem três funções que funcionam exatamente como essa linha de montagem: map() transforma cada item, filter() mantém só os itens que você quer e reduce() combina tudo em um único resultado. Juntas, elas permitem processar coleções de dados de um jeito limpo e legível.

Neste tutorial, você vai aprender como essas ferramentas funcionam, quando usá-las e quando uma list comprehension (compreensão de lista) pode ser uma escolha melhor. Ao final, você vai escrever pipelines de dados que deixariam qualquer supervisor de fábrica orgulhoso.

O que são funções de ordem superior?

Uma função de ordem superior é uma função que recebe outra função como argumento ou que retorna uma função como resultado. Só isso.

Você já usou uma sem perceber. A função embutida sorted() tem um parâmetro key no qual você passa uma função:

sorted() é uma função de ordem superior
words = ["banana", "apple", "cherry"]
# sorted() is a higher-order function
# It takes len as an argument - a function!
sorted_words = sorted(words, key=len)
print(sorted_words)
Saída
['apple', 'banana', 'cherry']

Aqui, len é passada como argumento para sorted(). A função sorted chama len em cada item para decidir a ordem. Você não chamou len() por conta própria: só disse a sorted qual função usar.

map(), filter() e reduce() funcionam todas assim. Você entrega a elas uma função e uma coleção, e elas aplicam essa função aos itens. É isso que as torna funções de ordem superior.

map(): transforme cada item

map() recebe uma função e um iterável (como uma lista), aplica a função a cada item e retorna os resultados transformados. Pense nela como a "estação de moldagem" da nossa linha de montagem.

A sintaxe é: map(function, iterable). Ela retorna um objeto map, que normalmente você converte em lista.

Usando map() para dobrar cada número
numbers = [1, 2, 3, 4, 5]
# Double every number
def double(x):
return x * 2
result = list(map(double, numbers))
print(result)
Saída
[2, 4, 6, 8, 10]

map(double, numbers) chama double(1), double(2), double(3) e assim por diante. Ela reúne todos os resultados. O list() em volta converte o objeto map em uma lista comum, para podermos exibi-la.

Como escrever uma função inteira só para dobrar um número parece exagero, map() costuma vir acompanhada de uma lambda, uma pequena função anônima:

map() com lambda e funções embutidas
numbers = [1, 2, 3, 4, 5]
# Same thing, but with a lambda
result = list(map(lambda x: x * 2, numbers))
print(result)
# More examples
names = ["alice", "bob", "charlie"]
print(list(map(str.upper, names)))
prices = [10.5, 20.3, 5.99]
print(list(map(round, prices)))
Saída
[2, 4, 6, 8, 10]
['ALICE', 'BOB', 'CHARLIE']
[10, 20, 6]

Você pode passar qualquer função para map(): suas próprias funções, lambdas ou funções embutidas como str.upper, round, len ou int.

filter(): mantenha só o que você precisa

filter() recebe uma função e um iterável. A função precisa retornar True ou False para cada item. Só ficam os itens para os quais a função retorna True. Pense nela como o controle de qualidade da linha de montagem: as peças com defeito são retiradas.

Usando filter() para manter os números pares
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Keep only even numbers
def is_even(x):
return x % 2 == 0
result = list(filter(is_even, numbers))
print(result)
Saída
[2, 4, 6, 8, 10]

filter(is_even, numbers) chama is_even(1), que retorna False (então o 1 é descartado), is_even(2) retorna True (então o 2 fica), e assim por diante. Só os itens que passam no teste sobrevivem.

Mais exemplos de filter()
words = ["hello", "", "world", "", "python", ""]
# Remove empty strings - filter with bool
result = list(filter(bool, words))
print(result)
# Keep words longer than 4 characters
long_words = list(filter(lambda w: len(w) > 4, words))
print(long_words)
# Keep positive numbers
numbers = [-3, -1, 0, 2, 5, -4, 8]
positives = list(filter(lambda x: x > 0, numbers))
print(positives)
Saída
['hello', 'world', 'python']
['hello', 'world', 'python']
[2, 5, 8]

Passar bool para filter() é um truque esperto. Strings vazias, zero, None e listas vazias são todos "falsy" (contam como falso) em Python: bool() retorna False para eles. Então filter(bool, items) remove todos os valores falsy.

Combinando map() e filter()

O verdadeiro poder vem de encadear essas funções. Primeiro filtre para selecionar os itens, depois aplique map para transformá-los, exatamente como as estações de uma linha de montagem.

Encadeando filter() e map()
scores = [45, 82, 91, 67, 55, 38, 73, 88, 95, 60]
# Step 1: Filter passing scores (>= 60)
passing = filter(lambda s: s >= 60, scores)
# Step 2: Add 5 bonus points to each passing score
boosted = map(lambda s: s + 5, passing)
# Convert to list and print
result = list(boosted)
print(result)
Saída
[87, 96, 72, 78, 93, 100, 65]

Como filter() e map() são preguiçosas, você pode encadeá-las sem criar listas intermediárias. Os dados passam pelo pipeline de forma eficiente.

Aqui está um exemplo mais prático, que processa uma lista de preços de produtos:

Pipeline prático: filtrar e depois transformar
prices = [12.99, 5.50, 89.99, 3.25, 45.00, 2.99, 150.00]
# Keep prices over $10, then apply 20% discount
result = list(
map(
lambda p: round(p * 0.8, 2),
filter(lambda p: p > 10, prices)
)
)
print(result)
Saída
[10.39, 71.99, 36.0, 120.0]

reduce(): combine todos os itens em um só

reduce() recebe uma função e um iterável e combina todos os itens em um único valor. É a última estação da linha de montagem: todas as peças são montadas em um só produto.

Diferente de map() e filter(), reduce() não é uma função embutida. Você precisa importá-la do módulo functools.

Usando reduce() para combinar valores
from functools import reduce
numbers = [1, 2, 3, 4, 5]
# Sum all numbers: ((((1+2)+3)+4)+5) = 15
total = reduce(lambda a, b: a + b, numbers)
print(f"Sum: {total}")
# Multiply all numbers: ((((1*2)*3)*4)*5) = 120
product = reduce(lambda a, b: a * b, numbers)
print(f"Product: {product}")
Saída
Sum: 15
Product: 120

Veja como reduce() funciona, passo a passo, no caso da soma. A função recebe dois argumentos: o resultado acumulado até agora (a) e o próximo item (b):

  • Começa com os dois primeiros itens: a=1, b=2 dá 3
  • Pega esse resultado e o próximo item: a=3, b=3 dá 6
  • Continua: a=6, b=4 dá 10
  • Por fim: a=10, b=5 dá 15
  • Mais exemplos de reduce()
    from functools import reduce
    # Find the longest word
    words = ["cat", "elephant", "dog", "hippopotamus"]
    longest = reduce(lambda a, b: a if len(a) >= len(b) else b, words)
    print(f"Longest word: {longest}")
    # Join words with a separator
    result = reduce(lambda a, b: f"{a} & {b}", ["Alice", "Bob", "Charlie"])
    print(result)
    Saída
    Longest word: hippopotamus
    Alice & Bob & Charlie

    map/filter versus compreensões de lista

    O Python oferece outra forma de transformar e filtrar listas: as compreensões de lista (list comprehensions). Muitas vezes elas geram um código mais legível do que map() e filter(). Vamos comparar.

    Usando map() e filter()
    numbers = [1, 2, 3, 4, 5, 6]
    
    # Double even numbers
    evens = filter(lambda x: x % 2 == 0, numbers)
    result = list(map(lambda x: x * 2, evens))
    print(result)  # [4, 8, 12]
    Usando uma compreensão de lista
    numbers = [1, 2, 3, 4, 5, 6]
    
    # Double even numbers
    result = [x * 2 for x in numbers if x % 2 == 0]
    print(result)  # [4, 8, 12]

    A compreensão faz a filtragem e o mapeamento em uma única linha legível. Para transformações simples, as compreensões costumam ser a melhor escolha em Python.

    Então, quando usar map() e filter()? Elas são úteis quando você já tem uma função com nome para aplicar:

    map() brilha com funções nomeadas
    # When you have a named function, map() reads nicely
    names = ["alice", "bob", "charlie"]
    print(list(map(str.capitalize, names)))
    # Equivalent comprehension - a bit more verbose
    print([name.capitalize() for name in names])
    Saída
    ['Alice', 'Bob', 'Charlie']
    ['Alice', 'Bob', 'Charlie']

    Exercícios práticos

    Hora de praticar. Estes exercícios começam com funções isoladas e avançam até combiná-las em pipelines. Lembre-se de envolver map() e filter() em list() na hora de exibir o resultado.

    Exercício 1: eleve cada número ao quadrado
    Escreva o código

    Use map() com uma lambda para elevar ao quadrado cada número da lista [1, 2, 3, 4, 5].

    Exiba o resultado como uma lista.

    Saída esperada:

    [1, 4, 9, 16, 25]
    numbers = [1, 2, 3, 4, 5]
    # Use map() to square each number
    Exercício 2: remova as palavras curtas
    Escreva o código

    Use filter() com uma lambda para manter só as palavras com mais de 3 caracteres.

    Dados: ["hi", "hello", "hey", "world", "ok", "python"]

    Exiba o resultado como uma lista.

    Saída esperada:

    ['hello', 'world', 'python']
    words = ["hi", "hello", "hey", "world", "ok", "python"]
    # Use filter() to keep words longer than 3 characters
    Exercício 3: preveja a saída do pipeline
    Preveja a saída

    Leia este código e preveja a saída. Depois, escreva uma instrução print() que produza exatamente a mesma saída.

    numbers = [10, 25, 30, 45, 50]
    result = list(map(lambda x: x // 10, filter(lambda x: x >= 30, numbers)))
    print(result)

    Pense passo a passo: o que filter mantém e, depois, o que map faz com cada item?

    # Print the exact output
    Exercício 4: conserte o pipeline quebrado
    Corrija o erro

    Este código deveria converter uma lista de temperaturas em texto, como ["32F", "100F", "212F"], em números inteiros em Celsius. Mas ele tem dois bugs.

    Saída esperada:

    [0, 38, 100]

    Fórmula: Celsius = (Fahrenheit - 32) * 5 / 9, depois arredonde para o inteiro mais próximo.

    temps = ["32F", "100F", "212F"]
    # Bug 1: Need to extract the number from the string
    # Bug 2: Formula or conversion issue
    result = list(map(lambda t: int((t - 32) * 5 / 9), temps))
    print(result)
    Exercício 5: calcule o produto com reduce()
    Escreva o código

    Use reduce() do módulo functools para calcular o produto de todos os números da lista [2, 3, 4, 5].

    O produto é 2 * 3 * 4 * 5 = 120.

    Exiba o resultado.

    Saída esperada:

    120
    from functools import reduce
    numbers = [2, 3, 4, 5]
    # Use reduce() to multiply all numbers together
    Exercício 6: monte um pipeline de dados
    Escreva o código

    Dada uma lista de notas de alunos, monte um pipeline que:

    1. Remova as notas de reprovação (mantenha só as notas >= 60)

    2. Ajuste cada nota aprovada somando 10 (use map)

    3. Limite as notas a 100 (use map com min)

    Dados: [45, 82, 55, 91, 67, 38, 73, 95]

    Exiba a lista final.

    Saída esperada:

    [92, 100, 77, 83, 100]

    Dica: para limitar a 100, use min(score, 100).

    scores = [45, 82, 55, 91, 67, 38, 73, 95]
    # Step 1: Filter passing scores (>= 60)
    # Step 2: Add 10 bonus points
    # Step 3: Cap at 100
    Exercício 7: reescreva como uma compreensão de lista
    Melhore o código

    Reescreva este pipeline de map/filter como uma única compreensão de lista que produza a mesma saída.

    Código original:

    words = ["Hello", "WORLD", "Python", "CODE", "test"]
    result = list(map(str.lower, filter(lambda w: len(w) > 4, words)))

    Escreva uma compreensão de lista que produza o mesmo resultado e exiba-o.

    Saída esperada:

    ['hello', 'world', 'python']
    words = ["Hello", "WORLD", "Python", "CODE", "test"]
    # Refactor to a list comprehension
    result = [] # Replace with your comprehension
    print(result)

    Resumo

    Veja o que você aprendeu sobre as ferramentas funcionais do Python:

    FunçãoPara que serveRetorna
    map(fn, iterable)Transformar cada itemObjeto map (preguiçoso)
    filter(fn, iterable)Manter os itens para os quais fn retorna TrueObjeto filter (preguiçoso)
    reduce(fn, iterable)Combinar todos os itens em um único valorUm único valor
    Função de ordem superiorUma função que recebe ou retorna uma funçãoDepende da função

    Na prática: use compreensões de lista na maioria das tarefas de transformar e filtrar em Python. Recorra a map() e filter() quando tiver uma função com nome para aplicar ou precisar de avaliação preguiçosa. Use reduce() com moderação: as funções embutidas do Python resolvem melhor a maioria dos casos.

    O que vem a seguir?

    Agora você tem uma base sólida em funções Python. Em seguida, explore o Tratamento de erros para aprender a escrever código que lida com erros de forma elegante, em vez de travar.

    Tutoriais relacionados

    Este tutorial foi útil?