Funções Lambda do Python: Sintaxe, usos reais e quando não usá-los
Um lambda é uma função minúscula que você pode escrever em uma linha, exatamente onde for necessário. Aprenda a sintaxe, os lugares onde os lambdas realmente ajudam, a armadilha que pega desenvolvedores experientes e quando uma função normal é simplesmente melhor.
- Um lambda é uma função anônima limitada a uma única expressão.
- Seu melhor uso é como argumento curto, especialmente
keyparasorted,minemax. - A compreensão de uma lista geralmente é mais clara que
mapoufiltercom um lambda. - Se você atribuir um lambda a um nome, escreva
def.
Você precisa classificar os produtos por preço. Escrever uma função nomeada separada apenas para dizer “usar o preço” parece muita cerimônia. Funções lambda do Python permitem definir aquele pequeno pedaço de lógica in-line, exatamente onde você o usa.
Lambdas são úteis, mas também fáceis de usar em excesso. Este guia mostra onde eles realmente ajudam e onde dificultam a leitura do código. Executamos todos os exemplos no Python 3.13 e a saída mostrada vem dessa execução.
O que é um lambda?
Um lambda é uma função sem nome, escrita com a palavra-chave lambda:
lambda arguments: expression
Recebe qualquer número de argumentos e retorna o valor de uma única expressão automaticamente. Não há palavra-chave return e nenhum corpo de declarações.
square = lambda x: x * x
print(square(4)) # 16
print((lambda a, b=10: a + b)(5)) # 15
A segunda linha define um lambda com um argumento padrão e o chama imediatamente. Você raramente escreveria isso em código real, mas mostra que um lambda é um objeto de função comum.
lambda versus def
Esses dois produzem funções que se comportam da mesma forma:
square = lambda x: x * x
def square_def(x):
return x * x
print(square(4), square_def(4)) # 16 16
print(square.__name__, square_def.__name__) # <lambda> square_def
Veja os nomes. Cada lambda é chamado apenas <lambda>, portanto, mensagens de erro e logs não podem dizer qual deles falhou. Esta é a principal razão pela qual guias de estilo como o PEP 8 recomendam um def sempre que você quiser dar um nome a uma função.
| Recurso | lambda |
definitivamente |
|---|---|---|
| Nome | Anônimo | Nomeado |
| Corpo | Uma expressão | Qualquer número de declarações |
| Retorno | Implícito | Explícito return |
| Docstring e dicas de tipo | Não compatível | Suportado |
| Rastreamentos legíveis | Programas <lambda> |
Mostra o nome |
| Melhor para | Argumentos curtos e descartáveis | Todo o resto |
Classificando com chave: o melhor uso
Funções como sorted, min e max aceitam uma função key que decide o que comparar. É aqui que os lambdas brilham:
products = [("pen", 10), ("bag", 900), ("book", 250)]
sorted(products, key=lambda p: p[1])
# [('pen', 10), ('book', 250), ('bag', 900)]
max(products, key=lambda p: p[1])
# ('bag', 900)
Para classificar por vários itens, retorne uma tupla. Aqui, as pessoas são classificadas por idade, primeiro as mais velhas e depois por nome:
people = [{"name": "Asha", "age": 31}, {"name": "Ben", "age": 25},
{"name": "Dev", "age": 31}]
[p["name"] for p in sorted(people, key=lambda p: (-p["age"], p["name"]))]
# ['Asha', 'Dev', 'Ben']
O sinal de menos inverte a ordem apenas do número. Às vezes você nem precisa de um lambda, porque uma função existente já faz o trabalho. Compare a classificação padrão com uma que não diferencia maiúsculas de minúsculas:
names = ["Asha", "ben", "Chitra", "dev"]
sorted(names) # ['Asha', 'Chitra', 'ben', 'dev']
sorted(names, key=str.lower) # ['Asha', 'ben', 'Chitra', 'dev']
O padrão coloca todas as palavras em maiúsculas primeiro. Passar str.lower corrige isso sem qualquer lambda. O módulo operator oferece ajudantes semelhantes, como itemgetter(1) para lambda p: p[1].
mapear e filtrar
map aplica uma função a cada item e filter mantém os itens para os quais retorna verdadeiro. Ambos funcionam com lambdas, mas compare cada um com uma compreensão de lista:
nums = [1, 2, 3, 4, 5, 6]
list(map(lambda n: n * 10, nums)) # [10, 20, 30, 40, 50, 60]
[n * 10 for n in nums] # [10, 20, 30, 40, 50, 60]
list(filter(lambda n: n % 2 == 0, nums)) # [2, 4, 6]
[n for n in nums if n % 2 == 0] # [2, 4, 6]
Os resultados são idênticos e a maioria dos desenvolvedores Python acha a compreensão mais fácil de ler. Observe também que map e filter retornam iteradores preguiçosos, então você precisa de list() para ver os valores. Nosso guia para compreensão de listas em Python aborda esse estilo em profundidade. map ainda funciona bem com uma função nomeada existente, como em map(str.strip, lines).
reduzir
functools.reduce combina itens em um único valor, carregando um resultado contínuo:
from functools import reduce
reduce(lambda acc, n: acc + n, nums, 0) # 21
sum(nums) # 21
Para trabalhos comuns, como totais, use um recurso integrado como sum, max ou any. Mantenha reduce para casos mais raros e considere um loop simples se o lambda começar a parecer complicado.
Condições em um lambda
Você não pode usar uma instrução if em um lambda, mas pode usar uma expressão condicional:
label = lambda total: "large" if total >= 1000 else "small"
label(1200), label(300)
# ('large', 'small')
Uma condição é boa. Depois de começar a aninhá-los, os leitores terão que trabalhar duro, o que é um sinal claro para mudar para def com instruções if comuns.
Lambdas que retornam funções
Uma função pode criar e retornar um lambda que lembra um valor do seu entorno:
def multiplier(n):
return lambda x: x * n
double = multiplier(2)
double(7) # 14
Isso funciona por causa dos encerramentos, que nosso artigo sobre fechamento JavaScript explica em uma linguagem diferente. O functools.partial do Python oferece outra maneira de preencher previamente argumentos.
A armadilha da ligação tardia
Isso pega quase todo mundo eventualmente. Criamos três lambdas em um loop, esperando que cada um retornasse seu próprio número:
funcs = [lambda: i for i in range(3)]
[f() for f in funcs]
# [2, 2, 2]
Todos os três retornam 2. Um lambda não captura o valor de i quando é criado. Ele procura a variável quando ela é chamada, e então o loop termina, deixando i em 2. A solução usual é capturar o valor como um argumento padrão, já que os padrões são avaliados no momento da definição:
funcs = [lambda i=i: i for i in range(3)]
[f() for f in funcs]
# [0, 1, 2]
Isso não é exclusivo dos lambdas, pois def dentro de um loop se comporta da mesma maneira. Ele aparece com mais frequência com lambdas, porque eles são comumente criados em loops, como ao anexar retornos de chamada de botão.
Dica: Se você precisar de uma função por item, considere se precisa de muitas funções. Freqüentemente, uma única função que toma o item como argumento é mais clara e evita totalmente a armadilha.
Tabelas de consulta de pequenas funções
Lambdas se encaixam perfeitamente em um dicionário que mapeia nomes para pequenas operações:
ops = {
"add": lambda a, b: a + b,
"sub": lambda a, b: a - b,
}
ops["sub"](10, 3) # 7
Isso pode substituir uma longa cadeia de if e elif. O guia dicionário Python cobre mais padrões de dicionário, e o módulo operator já fornece operator.add e operator.sub.
Limites de lambdas
- Apenas uma expressão. Sem atribuições com
=, sem loops e semtryblocos. - Sem declarações. A escrita
lambda x: return xfalha comSyntaxError, como nosso teste confirmou. - Sem documentação ou dicas de tipo. Ferramentas e leitores recebem menos ajuda.
- Depuração mais difícil. Os erros apontam para
<lambda>em vez de um nome útil.
Lambdas ainda podem gerar exceções, é claro. O tratamento deles funciona da mesma forma que para qualquer função, conforme abordado em Tratamento de exceções do Python.
Quando não usar um lambda
| Situação | Melhor escolha |
|---|---|
| Atribuindo a um nome | definitivamente |
| A lógica precisa de mais de uma linha | definitivamente |
| Transformando ou filtrando uma lista | Uma compreensão de lista |
| Somando ou encontrando um máximo | sum, max, min |
| Obtendo um item ou atributo | operator.itemgetter ou attrgetter |
| O mesmo lambda aparece em vários lugares | Uma função nomeada que você pode testar |
Esse último ponto é importante. Vale a pena testar a lógica que vale a pena reutilizar, e uma função nomeada é muito mais fácil de testar, como mostra nosso tutorial pytest.
Considerações finais
Um bom lambda é curto o suficiente para ser lido rapidamente e usado uma vez, geralmente como argumento. As chaves de classificação são o exemplo clássico. Para verificar seu próprio código, pesquise = lambda e transforme-os em funções nomeadas. Em seguida, observe qualquer map ou filter com um lambda e veja se uma compreensão é melhor.
Perguntas frequentes
O que é uma função lambda em Python?
É uma pequena função anônima criada com a palavra-chave lambda. Recebe argumentos e retorna o valor de uma única expressão, sem nome ou instrução de retorno.
Um lambda Python pode ter várias linhas?
Não. Um lambda está limitado a uma expressão. Você pode dividi-lo em linhas entre colchetes, mas ainda não pode conter instruções, então use def para uma lógica mais complexa.
Posso usar if else em um lambda?
Você pode usar uma expressão condicional, como lambda x: “big” if x > 10 else “small”. Uma instrução if com um bloco não é permitida.
Os lambdas são mais rápidos que as funções normais?
Não de forma significativa. Ambos criam o mesmo tipo de objeto de função. Escolha entre eles pela legibilidade, não pelo desempenho.
Devo usar mapa com lambda ou compreensão de lista?
A maioria dos desenvolvedores Python prefere uma compreensão de lista para facilitar a leitura. map é razoável quando você já tem uma função nomeada, como map(str.strip, lines).
Continue aprendendo
Precisa de ajuda com testes, WordPress ou SEO?
Ajudamos as equipes a fornecer software melhor e a expandir seus sites. Conte-nos no que você está trabalhando e sugeriremos um próximo passo claro.
Mais guias sobre testes, IA e desenvolvimento moderno
Gostou deste artigo? Escolha um tópico e vá direto para nossos tutoriais mais recentes.
Explicação das alucinações de IA: por que os modelos de linguagem inventam as coisas e como reduzi-las
Explicação das alucinações de IA: o que são, por que os modelos de linguagem as produzem, tipos comuns, como reduzi-las com aterramento e instruções…
Leia o artigo →DevOpsVariáveis de ambiente explicadas: arquivos .env, segredos e configuração bem feitos
Variáveis de ambiente explicadas com exemplos de Python que executamos: leitura e configuração, por que cada valor é uma string, arquivos .env, hera…
Leia o artigo →Desenvolvimento de softwareExplicação da limitação de taxa de API: algoritmos, cabeçalhos e tratamento de erros 429
Limitação de taxa de API explicada com uma simulação que executamos: token bucket, janela fixa, janela deslizante, 429 respostas, cabeçalhos de limi…
Leia o artigo →Automação de testesZombando em Python: unittest.mock, patch e os erros que fazem os testes mentirem
Zombaria em Python com unittest.mock, testado: Mock e return_value, side_effect, patch onde um nome é usado, especificação e autospec, zombaria de d…
Leia o artigo →Teste de softwareCobertura de código explicada: cobertura de linha versus filial e o que 100% realmente significa
Cobertura de código explicada com uma execução cobertura.py real: cobertura de linha, ramal e condição, leitura de um relatório, por que 100% de cob…
Leia o artigo →Bancos de dados e SQLDELETE vs TRUNCATE vs DROP em SQL: diferenças, reversão e quando usar cada um
DELETE vs TRUNCATE vs DROP explicado com SQL testado: o que cada um remove, rollback, aciona, redefinição de identidade, velocidade e como PostgreSQ…
Leia o artigo →Bancos de dados e SQLExibições SQL explicadas: crie, use e evite as armadilhas, com exemplos
Visualizações SQL explicadas com consultas que executamos: criação de uma visualização, resultados ao vivo, ocultação de colunas, desempenho, visual…
Leia o artigo →Desenvolvimento de softwareInterface TypeScript vs tipo: diferenças reais, testadas com o compilador
Interface TypeScript versus tipo, verificada com o compilador real: o que ambos podem fazer, o que apenas um pode fazer, mesclagem de declarações, e…
Leia o artigo →Desenvolvimento de softwarePython *args e **kwargs explicados: funções flexíveis com exemplos claros
Python *args e **kwargs explicados com o código que executamos: empacotamento e descompactação, ordem dos parâmetros, argumentos somente de palavras…
Leia o artigo →Desenvolvimento de softwareFunções Python Lambda: sintaxe, usos reais e quando não usá-los
Funções lambda do Python explicadas com o código que executamos: sintaxe, classificação com chave, mapa e filtro, fechamentos, armadilha de ligação …
Leia o artigo →Inteligência artificialO que são agentes de IA? Como eles funcionam, com um loop de agente simples que você pode executar
O que são agentes de IA? Um guia simples para o loop do agente, ferramentas, memória e proteções, com um pequeno loop Python que executamos, riscos …
Leia o artigo →DevOpsMonitoramento versus observabilidade: a verdadeira diferença, com logs, métricas e rastreamentos
Explicação do monitoramento versus observabilidade: falhas conhecidas e desconhecidas, logs, métricas e rastreamentos, um passo a passo do incidente…
Leia o artigo →DevOpsDocker Volumes vs Bind Mounts: persista os dados do contêiner da maneira certa
Volumes Docker versus montagens de ligação explicadas: por que os dados do contêiner desaparecem, volumes nomeados, montagens de ligação, tmpfs, exe…
Leia o artigo →Automação de testesTDD vs BDD: principais diferenças, um recurso criado de ambas as maneiras e quando usar cada um
TDD vs BDD explicado com um recurso de desconto construído em ambos os sentidos: refatoração vermelho-verde com o código que executamos, cenários da…
Leia o artigo →Desenvolvimento de softwareGit merge vs rebase: diferenças, exemplos e quando usar cada um
Git merge vs rebase explicado com saída real do log, uma tabela comparativa, a regra de ouro do rebase e um fluxo de trabalho seguro para equipes.
Leia o artigo →Desenvolvimento de softwareList comprehension em Python: sintaxe, exemplos e quando evitar
List comprehension em Python explicada: sintaxe, filtros, if-else, laços aninhados, tempos medidos e quando um laço for comum é a melhor escolha.
Leia o artigo →Bancos de dados e SQLSQL JOIN explicado com exemplos (Inner, Left, Right, Full)
Entenda os joins SQL passo a passo com tabelas e consultas de exemplo: INNER, LEFT, RIGHT, FULL, CROSS e SELF, além de erros comuns e dicas de desem…
Leia o artigo →