Voltar ao Glossario
Glossario Python

Lambda em Python: O que É e Como Funciona | Python Brasil

Aprenda lambda em Python: funções anônimas, uso com map/filter/sorted, closures, boas práticas e quando evitar. Guia completo com exemplos.

O que é Lambda?

Uma lambda em Python é uma função anônima — uma função sem nome — definida em uma única expressão. A palavra-chave lambda cria um objeto de função sem precisar do bloco def, tornando-a ideal para funções curtas usadas em um único lugar.

A sintaxe completa é:

lambda parametros: expressao

A expressao é avaliada e retornada automaticamente — não existe return explícito. Lambda suporta todos os tipos de parâmetros que def suporta: posicionais, com valor padrão, *args e **kwargs.

Exemplos básicos

# Equivalência entre def e lambda
def dobro(x):
    return x * 2

dobro_lambda = lambda x: x * 2

print(dobro(5))         # 10
print(dobro_lambda(5))  # 10

# Múltiplos parâmetros
soma = lambda a, b: a + b
print(soma(3, 7))   # 10

# Parâmetro com valor padrão
potencia = lambda base, exp=2: base ** exp
print(potencia(3))      # 9
print(potencia(2, 10))  # 1024

# Condicional (ternário)
sinal = lambda x: 'positivo' if x > 0 else ('negativo' if x < 0 else 'zero')
print(sinal(-5))   # negativo
print(sinal(0))    # zero

Uso com funções built-in

O principal poder das lambdas aparece quando combinadas com map(), filter(), sorted() e max()/min():

numeros = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# filter — mantém elementos onde a lambda retorna True
pares = list(filter(lambda x: x % 2 == 0, numeros))
# [2, 4, 6, 8, 10]

# map — transforma cada elemento
cubos = list(map(lambda x: x ** 3, numeros))
# [1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]

# sorted com key — ordena por critério personalizado
alunos = [('Ana', 8.5), ('Bruno', 7.2), ('Carla', 9.1), ('Diego', 7.2)]
por_nota = sorted(alunos, key=lambda aluno: aluno[1], reverse=True)
# [('Carla', 9.1), ('Ana', 8.5), ('Bruno', 7.2), ('Diego', 7.2)]

# Ordenacao multipla: nota decrescente, nome crescente como desempate
por_nota_nome = sorted(alunos, key=lambda a: (-a[1], a[0]))
# [('Carla', 9.1), ('Ana', 8.5), ('Bruno', 7.2), ('Diego', 7.2)]

# max/min com key
mais_novo = min([{'nome': 'Ana', 'idade': 25}, {'nome': 'Bruno', 'idade': 22}],
                key=lambda p: p['idade'])
print(mais_novo['nome'])   # Bruno

functools.reduce com lambda

from functools import reduce

numeros = [1, 2, 3, 4, 5]

# Soma acumulada
total = reduce(lambda acc, x: acc + x, numeros)
print(total)   # 15

# Produto
produto = reduce(lambda acc, x: acc * x, numeros)
print(produto)   # 120

# Achatar uma lista de listas (flatten)
listas = [[1, 2], [3, 4], [5]]
plana = reduce(lambda acc, x: acc + x, listas)
print(plana)   # [1, 2, 3, 4, 5]

# Encontrar o máximo sem usar max()
maximo = reduce(lambda a, b: a if a > b else b, numeros)
print(maximo)   # 5

Closures com lambda

Lambdas capturam variáveis do escopo ao redor (closure), mas esse comportamento pode gerar surpresas:

# Closure funciona corretamente com parâmetro com valor padrão
def criar_multiplicadores(lista_n):
    return [lambda x, n=n: x * n for n in lista_n]

dobro, triplo, quadruplo = criar_multiplicadores([2, 3, 4])
print(dobro(5))     # 10
print(triplo(5))    # 15
print(quadruplo(5)) # 20

# ARMADILHA CLÁSSICA: captura por referência, não por valor
multiplicadores_errados = [lambda x: x * n for n in [2, 3, 4]]
# Todas as lambdas capturam a mesma variável 'n' — que ao final do loop vale 4
print(multiplicadores_errados[0](5))   # 20 (esperado: 10!)
print(multiplicadores_errados[1](5))   # 20 (esperado: 15!)
print(multiplicadores_errados[2](5))   # 20 (correto por acaso)

# Solucao: use o parametro padrao para capturar o valor no momento da criacao
multiplicadores_corretos = [lambda x, n=n: x * n for n in [2, 3, 4]]
print(multiplicadores_corretos[0](5))  # 10
print(multiplicadores_corretos[1](5))  # 15

Lambda com defaultdict

from collections import defaultdict

# defaultdict aceita um callable sem argumentos como factory
contagem = defaultdict(lambda: 0)
for letra in 'abracadabra':
    contagem[letra] += 1
print(dict(contagem))
# {'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1}

# Factory mais complexa
inventario = defaultdict(lambda: {'quantidade': 0, 'preco': 0.0})
inventario['maçã']['quantidade'] += 10
inventario['maçã']['preco'] = 2.50
print(inventario['maçã'])    # {'quantidade': 10, 'preco': 2.5}
print(inventario['banana'])  # {'quantidade': 0, 'preco': 0.0}

Lambda vs módulo operator

O módulo operator oferece equivalentes funcionais de operadores Python, geralmente mais rápidos que lambdas:

import operator

dados = [{'nome': 'Ana', 'idade': 25}, {'nome': 'Bruno', 'idade': 22}]

# Lambda vs operator.itemgetter
sorted(dados, key=lambda d: d['nome'])          # lambda
sorted(dados, key=operator.itemgetter('nome'))   # operator (mais rápido)

# operator.attrgetter para objetos
from dataclasses import dataclass

@dataclass
class Produto:
    nome: str
    preco: float

produtos = [Produto('Café', 15.0), Produto('Açúcar', 8.5)]
mais_barato = min(produtos, key=operator.attrgetter('preco'))
# equivalente a: key=lambda p: p.preco

# operator.methodcaller
palavras = ['banana', 'MAÇÃ', 'cereja']
ordenadas = sorted(palavras, key=operator.methodcaller('lower'))
# equivalente a: key=lambda s: s.lower()

Lambda em callbacks de GUI (tkinter)

import tkinter as tk

def criar_interface():
    janela = tk.Tk()
    janela.title("Calculadora Simples")

    resultado = tk.StringVar(value="0")
    tk.Label(janela, textvariable=resultado, font=('Arial', 24)).pack()

    # Lambda captura o valor atual de 'n' no momento de criação do botão
    for n in range(10):
        tk.Button(
            janela,
            text=str(n),
            command=lambda v=n: resultado.set(str(v))
        ).pack(side=tk.LEFT)

    # Sem o truque n=n, todas as lambdas apontariam para n=9
    tk.mainloop()

Limitações do lambda

Lambda tem restrições importantes que def não tem:

# 1. Apenas UMA expressão — sem múltiplas instruções
# f = lambda x: x = x + 1; return x   # SyntaxError

# 2. Sem docstring
def com_doc(x):
    """Retorna o dobro de x."""
    return x * 2

# lambda x: x * 2  — não tem como adicionar docstring

# 3. Sem anotações de tipo
# f = lambda x: int -> int: x * 2   # SyntaxError

# 4. Sem statements: if sem else, while, for, try/except
# f = lambda x: if x > 0: x else -x   # SyntaxError (sem ternário)
# f = lambda x: x if x > 0 else -x    # OK — isso é uma expressao

# 5. Sem yield (não pode ser generator)
# f = lambda: yield 42   # SyntaxError

Anti-padrões comuns

# EVITE: atribuir lambda a variável — use def
# Ruim (PEP 8 desaprova explicitamente)
quadrado = lambda x: x ** 2

# Bom
def quadrado(x):
    return x ** 2

# EVITE: lambda que chama outra função sem necessidade
# Ruim
resultado = map(lambda x: str(x), numeros)

# Bom — passe a função diretamente
resultado = map(str, numeros)

# EVITE: lambda complexa e ilegível
# Ruim
processar = lambda dados: {k: v for k, v in dados.items() if v is not None and isinstance(v, (int, float))}

# Bom — use def com nome descritivo
def filtrar_numericos(dados):
    """Retorna apenas os pares chave-valor com valores numéricos."""
    return {k: v for k, v in dados.items()
            if v is not None and isinstance(v, (int, float))}

Orientação do PEP 8

O guia de estilo oficial do Python é explícito sobre lambda:

“Always use a def statement instead of an assignment statement that binds a lambda expression directly to an identifier.”

Em outras palavras: se você precisa dar um nome à função, use def. A única exceção razoável são casos onde a lambda é passada diretamente como argumento — especialmente em key=, command= ou callbacks similares.

Quando usar lambda: resumo

Use lambda quando:

  • A função tem uma única expressão simples.
  • É usada apenas uma vez, diretamente como argumento.
  • O contexto deixa claro o propósito (ex.: key=lambda x: x[1]).

Evite lambda quando:

  • A lógica tem mais de uma etapa ou precisa de tratamento de erros.
  • A função será reutilizada ou precisa de documentação.
  • A expressão for longa o suficiente para dificultar a leitura.

Termos Relacionados

  • List Comprehension — Alternativa mais pythonica a map/filter com lambda
  • Decorators — Funções que modificam outras funções em Python
  • Generators — Funções que produzem valores sob demanda com yield