Funções Lambda em Python: Um guia claro com exemplos práticos
Updated on
Todo projeto Python acumula pequenas funções auxiliares. Uma função que dobra um número. Outra que remove espaços em branco. Mais uma que extrai um sobrenome de um dicionário. Cada uma tem duas ou três linhas, é usada exatamente uma vez e polui o módulo com nomes que você nunca vai lembrar. As funções lambda em Python resolvem esse problema permitindo que você defina funções pequenas e descartáveis exatamente onde precisa delas -- sem def, sem nome, sem espaço vertical desperdiçado.
Este guia cobre tudo o que você precisa saber sobre funções lambda em Python: a sintaxe, as funções embutidas com as quais elas se combinam, padrões práticos para código do mundo real e as situações específicas em que você deve evitá-las.
O que é uma função Lambda?
Uma função lambda é uma função anônima de expressão única. "Anônima" significa que ela não tem nome. "Expressão única" significa que o corpo da função é exatamente uma expressão cujo resultado é automaticamente retornado. Python avalia essa expressão e retorna o resultado -- nenhuma instrução return é necessária.
O termo vem do cálculo lambda, um sistema formal em lógica matemática. Mas você não precisa entender a matemática. No Python prático, um lambda é simplesmente uma forma mais curta de escrever uma função pequena.
Aqui está uma função regular e seu equivalente lambda:
# Regular function
def double(x):
return x * 2
print(double(5))
# 10
# Lambda equivalent
double_lambda = lambda x: x * 2
print(double_lambda(5))
# 10Ambas produzem o mesmo resultado. A versão lambda cabe em uma linha e pula a cerimônia do def e return.
Sintaxe Lambda
A sintaxe para um lambda em Python é:
lambda arguments: expressionlambda-- a palavra-chave que sinaliza uma função anônima.arguments-- zero ou mais parâmetros, separados por vírgulas. Sem parênteses necessários.expression-- uma expressão única que é avaliada e retornada. Sem instruções (sem blocosif, sem laçosfor, sem atribuições com=).
Alguns exemplos rápidos para mostrar o alcance:
# No arguments
greet = lambda: "Hello, world!"
print(greet())
# Hello, world!
# One argument
square = lambda x: x ** 2
print(square(9))
# 81
# Two arguments
add = lambda a, b: a + b
print(add(3, 7))
# 10
# Default argument
power = lambda base, exp=2: base ** exp
print(power(3))
# 9
print(power(3, 3))
# 27A restrição principal é que o corpo deve ser uma expressão única. Você não pode escrever lógica multilinha, usar instruções if (embora possa usar expressões condicionais), ou incluir atribuições. Isso é intencional -- lambdas são feitos para operações simples.
Lambda com map() -- Transformando listas
map() aplica uma função a cada elemento de um iterável e retorna um iterador. Funções lambda são o companheiro natural do map() porque a transformação é frequentemente simples o suficiente para ser expressa em uma linha.
numbers = [1, 2, 3, 4, 5]
# Square each number
squared = list(map(lambda x: x ** 2, numbers))
print(squared)
# [1, 4, 9, 16, 25]
# Convert temperatures from Celsius to Fahrenheit
celsius = [0, 20, 37, 100]
fahrenheit = list(map(lambda c: round(c * 9/5 + 32, 1), celsius))
print(fahrenheit)
# [32.0, 68.0, 98.6, 212.0]
# Extract first names from full names
names = ["Ada Lovelace", "Grace Hopper", "Alan Turing"]
first_names = list(map(lambda name: name.split()[0], names))
print(first_names)
# ['Ada', 'Grace', 'Alan']map() com um lambda é uma alternativa limpa a uma compreensão de lista quando a lógica de mapeamento é uma transformação direta de uma etapa. Para transformações mais complexas, compreensões de lista tendem a ser mais legíveis.
Lambda com filter() -- Filtrando elementos
filter() recebe uma função e um iterável, e retorna um iterador que produz apenas os elementos para os quais a função retorna True. Funções lambda facilitam a definição do predicado inline.
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Keep only even numbers
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens)
# [2, 4, 6, 8, 10]
# Keep strings longer than 4 characters
words = ["cat", "elephant", "dog", "butterfly", "ant"]
long_words = list(filter(lambda w: len(w) > 4, words))
print(long_words)
# ['elephant', 'butterfly']
# Filter out None values
data = [1, None, 3, None, 5, None, 7]
clean = list(filter(lambda x: x is not None, data))
print(clean)
# [1, 3, 5, 7]Assim como map(), a combinação filter() + lambda funciona melhor para condições simples. Se a lógica de filtragem envolve múltiplas verificações, uma compreensão de lista ou uma função nomeada geralmente é mais clara.
Lambda com sorted() e sort() -- Chaves de ordenação personalizadas
Ordenação é um dos usos mais comuns e práticos para funções lambda. A função sorted() e o método .sort() aceitam um parâmetro key -- uma função que extrai um valor de comparação de cada elemento.
# Sort strings by length
fruits = ["banana", "kiwi", "strawberry", "fig", "apple"]
by_length = sorted(fruits, key=lambda s: len(s))
print(by_length)
# ['fig', 'kiwi', 'apple', 'banana', 'strawberry']
# Sort tuples by the second element
pairs = [(1, 'b'), (3, 'a'), (2, 'c')]
by_second = sorted(pairs, key=lambda pair: pair[1])
print(by_second)
# [(3, 'a'), (1, 'b'), (2, 'c')]
# Sort dictionaries by a specific key
students = [
{"name": "Alice", "grade": 88},
{"name": "Bob", "grade": 95},
{"name": "Charlie", "grade": 72},
]
by_grade = sorted(students, key=lambda s: s["grade"], reverse=True)
for s in by_grade:
print(f"{s['name']}: {s['grade']}")
# Bob: 95
# Alice: 88
# Charlie: 72Ordenação com lambda é tão amplamente usada que se tornou um padrão idiomático do Python. Sempre que você precisar ordenar objetos complexos por um atributo ou campo específico, uma função key lambda é a abordagem padrão.
Ordenação com múltiplos critérios
Você pode retornar uma tupla do lambda para ordenar por múltiplos campos:
employees = [
{"name": "Alice", "dept": "Engineering", "salary": 95000},
{"name": "Bob", "dept": "Marketing", "salary": 72000},
{"name": "Charlie", "dept": "Engineering", "salary": 88000},
{"name": "Diana", "dept": "Marketing", "salary": 85000},
]
# Sort by department (ascending), then by salary (descending)
sorted_emp = sorted(employees, key=lambda e: (e["dept"], -e["salary"]))
for e in sorted_emp:
print(f"{e['dept']:12s} {e['name']:8s} ${e['salary']:,}")
# Engineering Alice $95,000
# Engineering Charlie $88,000
# Marketing Diana $85,000
# Marketing Bob $72,000Lambda com reduce() do functools
functools.reduce() aplica uma função de dois argumentos cumulativamente aos elementos de um iterável, reduzindo-o a um único valor. Funções lambda combinam naturalmente com reduce() para agregações concisas.
from functools import reduce
numbers = [1, 2, 3, 4, 5]
# Product of all numbers
product = reduce(lambda x, y: x * y, numbers)
print(product)
# 120
# Find the maximum value (for demonstration; use max() in practice)
largest = reduce(lambda a, b: a if a > b else b, numbers)
print(largest)
# 5
# Concatenate a list of strings
words = ["Python", " ", "lambda", " ", "functions"]
sentence = reduce(lambda a, b: a + b, words)
print(sentence)
# Python lambda functions
# Flatten a list of lists
nested = [[1, 2], [3, 4], [5, 6]]
flat = reduce(lambda acc, lst: acc + lst, nested)
print(flat)
# [1, 2, 3, 4, 5, 6]Um aviso: reduce() pode obscurecer a intenção. Para operações comuns como somar, use sum(). Para encontrar mín/máx, use min() e max(). Reserve reduce() com lambda para acumulações personalizadas onde nenhuma função embutida existe.
Lambda vs def -- Quando usar cada um
Esta é a pergunta que mais importa na prática. Lambda e def ambos criam objetos função, mas servem propósitos diferentes.
| Característica | lambda | def |
|---|---|---|
| Nome | Anônimo (sem nome) | Função nomeada |
| Corpo | Apenas expressão única | Múltiplas instruções, laços, condições |
| Retorno | Implícito (resultado da expressão) | Instrução return explícita |
| Docstrings | Não suportado | Suportado |
| Type hints | Não suportado | Suportado |
| Depuração | Mostra <lambda> nos rastreamentos | Mostra nome da função nos rastreamentos |
| Legibilidade | Melhor para operações simples e curtas | Melhor para qualquer coisa multi-etapa |
| Testabilidade | Mais difícil de testar isoladamente | Fácil de testar por nome |
| Reutilização | Tipicamente uso único, inline | Projetado para reutilização |
| Decoradores | Não pode usar sintaxe @decorator | Suporte completo a decoradores |
Quando usar Lambda
- Chaves de ordenação:
sorted(items, key=lambda x: x.name) - Operações rápidas de map/filter:
map(lambda x: x.strip(), lines) - Argumentos callback: funções que aceitam um parâmetro chamável
- Acesso simples a dicionário ou tupla:
key=lambda item: item[1]
Quando usar def
- A função tem mais de uma expressão
- Você precisa de um docstring ou type hints
- A função será chamada de vários lugares
- A lógica requer tratamento de erros ou ramificação
- Você precisa de um nome significativo nos rastreamentos de pilha para depuração
Regra geral: se o lambda não cabe confortavelmente em uma única linha, ou se você precisa lê-lo duas vezes para entender o que faz, use def em vez disso.
Lambda com múltiplos argumentos
Funções lambda podem aceitar qualquer número de argumentos, incluindo *args e **kwargs:
# Three arguments
volume = lambda l, w, h: l * w * h
print(volume(3, 4, 5))
# 60
# Using *args for variable arguments
sum_all = lambda *args: sum(args)
print(sum_all(1, 2, 3, 4, 5))
# 15
# Using **kwargs
build_greeting = lambda **kwargs: f"Hello, {kwargs.get('name', 'stranger')}!"
print(build_greeting(name="Alice"))
# Hello, Alice!
print(build_greeting())
# Hello, stranger!
# Conditional expression inside lambda
classify = lambda x: "positive" if x > 0 else ("zero" if x == 0 else "negative")
print(classify(5))
# positive
print(classify(0))
# zero
print(classify(-3))
# negativeNote a expressão condicional (a if condition else b) no último exemplo. Esta é a única maneira de adicionar lógica de ramificação dentro de um lambda. Funciona, mas aninhar múltiplas condições reduz a legibilidade rapidamente.
Lambda em operações com dicionários
Funções lambda são úteis para transformar e ordenar dados de dicionários:
# Sort a dictionary by value
scores = {"Alice": 88, "Bob": 95, "Charlie": 72, "Diana": 91}
sorted_scores = dict(sorted(scores.items(), key=lambda item: item[1], reverse=True))
print(sorted_scores)
# {'Bob': 95, 'Diana': 91, 'Alice': 88, 'Charlie': 72}
# Apply a transformation to all dictionary values
prices = {"apple": 1.20, "banana": 0.50, "cherry": 2.00}
discounted = {k: round(v * 0.9, 2) for k, v in prices.items()}
print(discounted)
# {'apple': 1.08, 'banana': 0.45, 'cherry': 1.8}
# Group items using a lambda as a key function
from itertools import groupby
data = ["apple", "avocado", "banana", "blueberry", "cherry", "cranberry"]
data_sorted = sorted(data, key=lambda x: x[0])
for letter, group in groupby(data_sorted, key=lambda x: x[0]):
print(f"{letter}: {list(group)}")
# a: ['apple', 'avocado']
# b: ['banana', 'blueberry']
# c: ['cherry', 'cranberry']Lambda com Pandas: df.apply() e df.sort_values()
Funções lambda são muito usadas no pandas para transformações ao nível de linha e ordenação personalizada. O método apply() executa uma função em cada linha ou coluna de um DataFrame, e lambda mantém o código inline.
import pandas as pd
df = pd.DataFrame({
"name": ["Alice", "Bob", "Charlie", "Diana"],
"score": [88, 95, 72, 91],
"department": ["Engineering", "Marketing", "Engineering", "Marketing"]
})
# Add a new column with a grade label
df["grade"] = df["score"].apply(lambda x: "A" if x >= 90 else ("B" if x >= 80 else "C"))
print(df)
# name score department grade
# 0 Alice 88 Engineering B
# 1 Bob 95 Marketing A
# 2 Charlie 72 Engineering C
# 3 Diana 91 Marketing AUsando Lambda com sort_values(key=)
O parâmetro key em sort_values() aceita uma função aplicada à coluna antes da ordenação:
import pandas as pd
df = pd.DataFrame({
"product": ["Widget A", "Widget B", "Widget C"],
"price": ["$29.99", "$9.50", "$149.00"]
})
# Sort by numeric price value (strip the $ sign first)
df_sorted = df.sort_values("price", key=lambda col: col.str.replace("$", "", regex=False).astype(float))
print(df_sorted)
# product price
# 1 Widget B $9.50
# 0 Widget A $29.99
# 2 Widget C $149.00Usando Lambda com apply() através de linhas
Defina axis=1 para aplicar um lambda a cada linha:
import pandas as pd
df = pd.DataFrame({
"first_name": ["Ada", "Grace", "Alan"],
"last_name": ["Lovelace", "Hopper", "Turing"],
"birth_year": [1815, 1906, 1912]
})
# Create a full name column
df["full_name"] = df.apply(lambda row: f"{row['first_name']} {row['last_name']}", axis=1)
# Calculate age (approximate, as of 2026)
df["approx_age"] = df["birth_year"].apply(lambda y: 2026 - y)
print(df)
# first_name last_name birth_year full_name approx_age
# 0 Ada Lovelace 1815 Ada Lovelace 211
# 1 Grace Hopper 1906 Grace Hopper 120
# 2 Alan Turing 1912 Alan Turing 114Padrões e expressões idiomáticas comuns de Lambda
Aqui estão padrões que você encontrará frequentemente em código Python de produção:
# 1. Default factory for collections.defaultdict
from collections import defaultdict
word_count = defaultdict(lambda: 0)
for word in ["apple", "banana", "apple", "cherry", "banana", "apple"]:
word_count[word] += 1
print(dict(word_count))
# {'apple': 3, 'banana': 2, 'cherry': 1}
# 2. Immediate invocation (IIFE - Immediately Invoked Function Expression)
result = (lambda x, y: x + y)(3, 4)
print(result)
# 7
# 3. Lambda as a callback in GUI or event-driven code
# button.on_click(lambda event: print(f"Clicked at {event.x}, {event.y}"))
# 4. Using lambda with min/max for custom comparisons
products = [
("Laptop", 999),
("Mouse", 25),
("Keyboard", 75),
("Monitor", 450),
]
cheapest = min(products, key=lambda p: p[1])
print(cheapest)
# ('Mouse', 25)
# 5. Lambda with conditional expression for data cleaning
clean = lambda s: s.strip().lower() if isinstance(s, str) else s
print(clean(" Hello World "))
# hello world
print(clean(42))
# 42Quando NÃO usar Lambda
Funções lambda têm limites claros. Usá-las além desses limites leva a código que é mais difícil de ler, depurar e manter.
Evite lambda quando:
- A lógica é complexa. Se você precisa de condições aninhadas, múltiplas operações ou qualquer forma de tratamento de erros, use
def.
# Bad -- hard to read
process = lambda x: x.strip().lower().replace(" ", "_") if isinstance(x, str) and len(x) > 0 else "empty"
# Good -- clear and testable
def process(x):
"""Normalize a string to a snake_case identifier."""
if not isinstance(x, str) or len(x) == 0:
return "empty"
return x.strip().lower().replace(" ", "_")
print(process(" Hello World "))
# hello_world-
Você atribui o lambda a uma variável para reutilização. PEP 8 recomenda explicitamente usar
defem vez de atribuir um lambda a um nome. Se a função merece um nome, dê a ela uma definição adequada. -
Você precisa de um docstring ou type hints. Funções lambda não suportam nenhum dos dois. Funções nomeadas suportam.
-
Depuração importa. Funções lambda aparecem como
<lambda>nos rastreamentos, o que torna difícil identificar qual lambda causou um erro quando você tem vários. -
A legibilidade sofre. Se um colega precisa de mais de três segundos para entender seu lambda, reescreva-o como uma função nomeada.
| Situação | Usar lambda | Usar def |
|---|---|---|
Chave de ordenação para sorted() | Sim | Apenas se complexo |
map()/filter() rápido | Sim | Se multi-etapa |
| Reutilizado em múltiplos lugares | Não | Sim |
| Ramificação complexa | Não | Sim |
| Precisa de um docstring | Não | Sim |
| Callback em API | Sim | Se a lógica cresce |
| Tratamento de erros necessário | Não | Sim |
Escrevendo e refatorando funções Lambda com RunCell
Trabalhar com funções lambda em notebooks Jupyter é comum em fluxos de trabalho de ciência de dados. Quando você está escrevendo chamadas complexas ao pandas apply() ou encadeando múltiplas operações map() e filter(), pode ser difícil saber se um lambda é a ferramenta certa ou se você deveria refatorar para uma função nomeada.
RunCell (opens in a new tab) é um agente de IA projetado para trabalhar diretamente dentro de notebooks Jupyter. Ele entende o contexto do seu notebook -- as variáveis na memória, os DataFrames com os quais você está trabalhando, os imports que você carregou -- e dá sugestões direcionadas.
Veja como o RunCell ajuda especificamente com funções lambda:
- Refatoração de lambda para def. Quando um lambda fica muito longo, o RunCell pode sugerir uma versão limpa com
def, type hints e um docstring, preservando o comportamento exato. - Dicas de performance. Se você está usando
df.apply(lambda ...)em um DataFrame grande, o RunCell pode sugerir alternativas vetorizadas usando operações nativas do pandas ou NumPy que rodam 10-100x mais rápido. - Explicações inline. Trabalhando com código de outra pessoa cheio de lambdas aninhados? O RunCell pode decompor o que cada lambda faz em linguagem simples, diretamente no notebook.
- Sugestões de padrões. Descreva o que você quer -- "ordenar esta lista de dicts por data, depois por nome" -- e o RunCell gera a chamada correta ao
sorted()com a função key lambda adequada.
Como o RunCell roda dentro do seu ambiente Jupyter existente, não há troca de contexto. Você fica no notebook e o agente de IA trabalha ao seu lado.
FAQ
O que é uma função lambda em Python?
Uma função lambda é uma função pequena e anônima definida com a palavra-chave lambda. Ela pode receber qualquer número de argumentos, mas só pode conter uma única expressão. O resultado da expressão é automaticamente retornado. Funções lambda são tipicamente usadas para operações curtas e descartáveis como chaves de ordenação, callbacks de map/filter e transformações inline.
Um lambda Python pode ter múltiplas linhas?
Não. Um lambda Python é restrito a uma única expressão. Você não pode usar múltiplas instruções, laços ou atribuições em um lambda. Se você precisa de lógica multilinha, use uma função def regular. Você pode, no entanto, usar uma expressão condicional (a if condition else b) dentro de um lambda para ramificação simples.
Qual é a diferença entre lambda e def em Python?
Ambos criam objetos função, mas diferem no escopo: lambda cria funções anônimas de expressão única usadas inline, enquanto def cria funções nomeadas que podem conter múltiplas instruções, docstrings, type hints e decoradores. Use lambda para operações simples de uso único; use def para qualquer coisa que precise de um nome, documentação ou lógica complexa.
Quando devo usar lambda em vez de uma compreensão de lista?
Use lambda com map() ou filter() quando a operação é uma transformação ou predicado simples e único. Use compreensões de lista quando você precisa tanto de filtragem quanto de transformação em uma etapa, ou quando a lógica se beneficia da estrutura [expr for x in iterable if condition]. No Python moderno, compreensões de lista são geralmente preferidas pela legibilidade, mas lambda é padrão para chaves de ordenação e parâmetros callback.
Funções lambda em Python são lentas?
Não. Funções lambda têm o mesmo desempenho que funções def equivalentes. O overhead de chamar qualquer uma é idêntico. No entanto, usar df.apply(lambda ...) no pandas é lento comparado a operações vetorizadas. O gargalo é a execução linha por linha do Python, não o lambda em si. Sempre que possível, substitua apply(lambda ...) por métodos embutidos do pandas ou NumPy para melhor desempenho.
Conclusão
Funções lambda em Python preenchem um nicho específico: funções curtas e anônimas que você define exatamente onde precisa delas. Elas são melhores como chaves de ordenação, callbacks de map()/filter() e transformações inline. Combinam naturalmente com sorted(), map(), filter(), reduce() e pandas apply().
As regras para usá-las bem são diretas:
- Mantenha-as em uma expressão simples.
- Use-as inline, não atribuídas a variáveis (diretriz PEP 8).
- Mude para
defno momento em que a lógica ficar difícil de ler. - No pandas, prefira operações vetorizadas sobre
apply(lambda ...)para desempenho. - Use expressões condicionais com moderação -- ternários aninhados em um lambda são uma armadilha de legibilidade.
Lambda é uma ferramenta, não um emblema de esperteza. O melhor código Python usa lambda onde simplifica e def onde clarifica. Conhecer a fronteira entre os dois é o que separa código legível de código que faz seu eu futuro (ou seus colegas de equipe) sofrer.