Funções de Alta Ordem e Lambda
Em Python, funções também são "valores" — podem ser atribuídas a variáveis, passadas para outras funções, como números e strings. Isso permite código muito conciso e elegante. Funções de alta ordem são funções que recebem outras funções como argumentos ou retornam funções. Esta lição abrirá um novo mundo para você.
1. Funções são Cidadãos de Primeira Classe
Em Python, funções podem ser manipuladas como qualquer outro valor:
Exemplo: Funções como Valores
def say_hello(name):
return f"Olá, {name}"
# Atribui uma função a uma variável
my_func = say_hello
print(my_func("Alice")) # Olá, Alice
# Passa uma função como argumento
def greet_with(func, name):
return func(name)
print(greet_with(say_hello, "Bob")) # Olá, Bob
# Retorna uma função a partir de uma função
def create_greeter(greeting):
def greeter(name):
return f"{greeting}, {name}!"
return greeter
say_hi = create_greeter("Oi")
say_hello = create_greeter("Olá")
print(say_hi("Alice")) # Oi, Alice!
print(say_hello("Bob")) # Olá, Bob!
2. map(): Transformação em Lote
map() aplica uma função a cada elemento de uma sequência e retorna um novo iterador:
Exemplo: map Transformação em Lote
# Elevar ao quadrado cada número em uma lista
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x ** 2, numbers))
print(squared) # [1, 4, 9, 16, 25]
# Converter lista de strings para maiúsculas
fruits = ["maçã", "banana", "cereja"]
upper_fruits = list(map(str.upper, fruits))
print(upper_fruits) # ['MAÇÃ', 'BANANA', 'CEREJA']
# Celsius para Fahrenheit
temps_c = [0, 10, 20, 30, 40]
temps_f = list(map(lambda c: c * 9 / 5 + 32, temps_c))
print(temps_f) # [32.0, 50.0, 68.0, 86.0, 104.0]
map()equivale a uma list comprehension:map(f, seq)≈[f(x) for x in seq]. Qual usar é questão de preferência — comprehensions são mais "pytônicas."
3. filter(): Filtragem em Lote
filter() seleciona elementos para os quais a função retorna True:
Exemplo: filter Dados
# Filtrar números pares
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens) # [2, 4, 6, 8, 10]
# Filtrar palavras com comprimento >= 5
words = ["cat", "elefante", "cachorro", "girafa", "formiga"]
long_words = list(filter(lambda w: len(w) >= 5, words))
print(long_words) # ['elefante', 'cachorro', 'girafa', 'formiga']
# Filtrar strings não vazias
data = ["hello", "", "world", "", "python"]
non_empty = list(filter(None, data)) # None significa "remover valores falsy"
print(non_empty) # ['hello', 'world', 'python']
filter()também equivale a uma comprehension:filter(f, seq)≈[x for x in seq if f(x)]. UsarNonecomo função equivale a remover todos os valores falsy ("",0,None,False, etc.).
4. Uso Avançado de sorted()
A Lição 11 cobriu o parâmetro key de sorted(). Vamos nos aprofundar:
Exemplo: Ordenação Personalizada com sorted
# Ordenar por atributo de objeto
students = [
{"name": "Alice", "score": 85},
{"name": "Bob", "score": 92},
{"name": "Charlie", "score": 78},
]
# Ordenar por pontuação decrescente
ranked = sorted(students, key=lambda s: s["score"], reverse=True)
for s in ranked:
print(f"{s['name']}: {s['score']}")
# Ordenar por comprimento do nome
sorted_by_name = sorted(students, key=lambda s: len(s["name"]))
print([s["name"] for s in sorted_by_name]) # ['Bob', 'Alice', 'Charlie']
Exemplo: Ordenação Multi-Nível (Dificuldade ⭐⭐)
# Ordenar por pontuação decrescente, depois por nome alfabeticamente
data = [
("Alice", 85),
("Bob", 92),
("Charlie", 85),
("Diana", 92),
]
def sort_key(item):
# Retorna tupla: primeiro por pontuação decrescente (negativo = reverso), depois por nome
return (-item[1], item[0])
sorted_data = sorted(data, key=sort_key)
for name, score in sorted_data:
print(f"{name}: {score}")
Saída:
Bob: 92
Diana: 92
Alice: 85
Charlie: 85
5. reduce(): Computação Acumulativa
reduce() acumula elementos em uma sequência, aplicando uma função a dois elementos por vez. Não é embutido; importe de functools:
Exemplo: reduce Computação Acumulativa
from functools import reduce
# Produto de todos os números
numbers = [1, 2, 3, 4, 5]
product = reduce(lambda x, y: x * y, numbers)
print(product) # 120 (1×2×3×4×5)
# Encontrar máximo
max_val = reduce(lambda a, b: a if a > b else b, [3, 1, 4, 1, 5])
print(max_val) # 5
# Concatenar strings
words = ["Hello", " ", "World", " ", "Python"]
sentence = reduce(lambda a, b: a + b, words)
print(sentence) # Hello World Python
Processo de Execução de reduce()
# reduce(lambda x, y: x + y, [1, 2, 3, 4])
# Passo 1: x=1, y=2 → 3
# Passo 2: x=3, y=3 → 6
# Passo 3: x=6, y=4 → 10
# Resultado: 10
reduce() vs laços: Tudo que reduce() pode fazer, um laço for também pode. reduce() é mais conciso e declarativo — você está dizendo "o que fazer" em vez de "como fazer." A desvantagem é que pode ser mais difícil de entender para iniciantes.
6. Expressões Lambda em Profundidade
Lambda, nomeado após a letra grega λ, é essencialmente uma função anônima — uma pequena função sem nome, usada e descartada.
Lambda vs Funções Regulares
Exemplo: Lambda vs Regular
# Função regular
def double(x):
return x * 2
# Expressão lambda
double = lambda x: x * 2
print(double(5)) # 10
Sintaxe Completa de Lambda
lambda parâmetros: expressão
# ↑ Equivalente a
def função_anônima(parâmetros):
return expressão
Múltiplos Parâmetros
Exemplo: Lambda com Múltiplos Parâmetros
add = lambda a, b: a + b
print(add(3, 5)) # 8
# Expressão ternária em lambda
max_val = lambda a, b: a if a > b else b
print(max_val(10, 20)) # 20
Quando Usar Lambda
Exemplo: Casos de Uso de Lambda
# ✅ Bom: transformação simples de uma linha como argumento para função de alta ordem
numbers = [1, 2, 3, 4]
result = list(map(lambda x: x ** 2, numbers))
# ❌ Ruim: lógica complexa que requer múltiplas linhas — use uma função def regular
Casos de Uso Comuns
- Pipelines de dados: Encadeie
map()→filter()→sorted()para processamento de dados. - Ordenação personalizada: Use
lambdacomo parâmetrokeypara várias regras de ordenação. - Callbacks de eventos: Passe funções como argumentos para frameworks GUI ou web.
- Fábricas de closure: Função externa retorna função interna para funcionalidade "parametrizada."
- Avaliação preguiçosa: Funções de alta ordem adiam a computação até que seja necessária.
❓ Perguntas Frequentes
P: Qual é melhor —
map()ou list comprehensions? R: A comunidade Python prefere list comprehensions — mais intuitivas, mais pytônicas.map()tem vantagens: ① Mais curto quando você tem um nome de função existente (map(str.upper, seq)vs[s.upper() for s in seq]); ② Retorna um iterador preguiçoso, economizando memória para grandes dados. Na maioria dos casos, list comprehensions são a melhor escolha. ⚠️ P: Lambda pode abranger múltiplas linhas? R: Não. A sintaxe lambda é restrita a expressões únicas. Para lógica de múltiplas linhas, defina uma função regular. O lambda do Python é deliberadamente mais fraco que em outras linguagens (como JavaScript) — Guido (criador do Python) acredita que "explícito é melhor que implícito." P:reduce()ainda é usado no Python moderno? R: Não muito. O próprio Guido não gostava dereduce(), achando difícil de entender. A maioria dos cenários dereduce()pode ser substituída por um laço ou uma função mais direta (comosum(),max()). No entanto,reduce()continua sendo um conceito importante na programação funcional.
📖 Resumo
- Funções são cidadãos de primeira classe em Python — podem ser atribuídas, passadas e retornadas
map(f, seq)aplica uma função a cada elemento; uselist()para converter em listafilter(f, seq)seleciona elementos onde a função retorna Truesorted(seq, key=f)aceita uma função para ordenação personalizadareduce(f, seq)acumula valores; importe defunctools- Lambda
lambda params: expressioné uma função anônima de uma linha para cenários simples
📝 Atividades
-
Básico (Dificuldade ⭐): Dado
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], usemap()efilter()para: filtrar números ímpares e calcular seus quadrados. Dica: Primeirofilterpara ímpares, depoismappara quadrados. -
Intermediário (Dificuldade ⭐⭐): Dada uma lista de dicionários
products = [{"name": "A", "price": 100}, {"name": "B", "price": 80}, {"name": "C", "price": 120}], usesorted()para ordenar por preço decrescente e exiba nomes e preços. -
Desafio (Dificuldade ⭐⭐⭐): Use
reduce()para implementar uma funçãoflatten(nested_list)que achata uma lista aninhada em um nível. Por exemplo,flatten([[1, 2], [3, 4], [5]])retorna[1, 2, 3, 4, 5]. Dica: Emreduce, use+para mesclar duas listas cada vez. Depois implemente o mesmo com uma list comprehension e compare as abordagens.



