Como utilizar a função lambda em Python
Neste artigo você aprenderá tudo sobre expressões lambda em Python. Verá como simplificar seu código, saberá onde utilizar e onde evitar.
Funções Anônimas
Funções anônimas estão presentes em muitas linguagens, em algumas sendo um conceito básico primordial da linguagem, é,
por exemplo, o caso do LISP
e do Haskell
.
História
As linguagens modernas que contém a função lambda
em geral bebem da mesma fonte, um modelo computacional chamado
“Lambda Calculus” inventado por Alonzo Church na década de 30.
Lambda Calculus e a lógica matemática são os precursores das linguagens funcionais, Python
não é uma linguagem
funcional, porém adotou desde o início (em 1994) alguns conceitos funcionais, com as funções reduce
, map
, filter
e lambda
.
que são funções anônimas?
Como o próprio nome já indica, função anônima é uma função não identificada, sem um “nome”, no caso, sem uma variável.
Na verdade, até podemos atribuí-las a uma variável, mas você verá no próximo tópico que isso não é uma boa prática.
Dependendo da linguagem a função lambda
pode ser chamada por nomes diferentes, algumas variações que você poderá ver
são:
- Função anônima.
- Função na forma
lambda
. - Função
lambda
. - Função literal.
- Expressão
lambda
. - Abstração
lambda
. - Modelo
lambda
.
Função lambda em Python
Veremos alguns exemplos simples de utilização de uma função lambda
, no decorrer do artigo realizaremos várias
demonstrações, mas só para você ir se acostumando com a sintaxe, veja como é a forma básica de uso para somar dois
números em Python.
lambda x, y: x + y
Definir a função lambda
da forma acima não tem nenhuma utilidade prática, para utilizar com os parâmetros podemos
efetuar da seguinte forma:
print((lambda x, y: x + y)(1, 2))
# 3
Também podemos armazenar a função lambda
e utilizar em mais de um contexto.
funcao_soma = lambda x, y: x + y
print(funcao_soma(1, 2))
# 3
print(funcao_soma(10, -6))
# 4
Ao decorrer do artigo veremos outros exemplos e outras formas de utilizar as funções lambda
em Python.
Utilizar a função lambda é uma boa prática?
Em Python as funções lambda
dividem muitas opiniões, algumas pessoas defendem o seu uso por permitir simplificar(pelo
menos em quantidades de linhas) os códigos em Python.
Ao mesmo tempo, existe um grupo que defende que as funções anônimas não são “Pythônicas”, inclusive existe um trecho no guia de estilo do Python(PEP 8), que diz:
“Sempre use uma instrução
def
em vez de uma instrução de atribuição que vincula uma expressãolambda
diretamente a um identificador.”
Fora esse uso associado a uma variável não tem nenhuma outra restrição da função lambda
no PEP 8
.
Verá logo abaixo vários exemplos de bons usos, onde, em geral, utilizar a expressão lambda
seria uma forma simples de
resolver um problema.
Diferenças entre uma função lambda e uma função convencional
Funções lambda
são semelhantes em muitos pontos em relação à forma convencional das funções, definidas com a diretiva
def
, algumas características próprias das funções lambda
são:
- Não podem conter outros comandos(
statements
), apenas expressões. - São definidas numa linha.
- Não é possível utilizar tipagem.
- Podem ser chamadas sem serem definidas previamente.
Analisaremos cada um dos pontos.
statements
)
Não podem conter outros comandos(Em funções lambdas
, diferentemente das convencionais, não é possível utilizar comandos como:
return
pass
assert
raise
Caso você tente utilizar irá ocorrer um erro de Syntax, isso pode ser um problema em alguns casos, afinal impossibilita tratar erros, mesmo os mais simples.
São definidas em uma linha
Esse ponto é auto explicativo, significa que as funções lambda
são one line expression
, ou expressões de uma linha,
mesmo que, na prática, podemos utilizar mais de uma linha para defini-las.
funcao_soma = (lambda x, y:
x + y)
Caso execute esse código acima verá que se trata de uma função válida.
Ser one line expression
como escrito na documentação significa, na verdade, que se trata de uma única expressão, mesmo
que separada em várias linhas diferentes.
Não é possível utilizar tipagem
Esse é um ponto interessante, muitos iniciantes acreditam que não existe tipagem em Python, mas isso é falso, como foi visto nesse artigo existe tipagem e utilizar traz uma série de vantagens.
Por exemplo, poderíamos definir a função normal de soma utilizando tipagem.
def funcao_soma(x: int, y: int) -> int:
return x + y
Não é possível fazer algo semelhante com as funções lambda
.
Podem ser chamadas sem serem definidas previamente
Com as funções lambda
, como já demonstrado anteriormente, podemos passar os atributos sem defini-las.
print((lambda x, y: x + y)(1, 2))
# 3
Não é possível fazer isso com as funções convencionais definidas com a diretiva def
.
Esse uso das funções lambda
são normalmente chamadas IIFE
(immediately invoked function execution
) ou em português
seria algo como EIFI
(Execução imediata de função invocada
), mas nunca vi esse termo sendo utilizado em português,
caso tenha alguma referência de tradução/utilização envie-me por gentileza.
Passando parâmetros
Existem várias formas de passagem de parâmetros para uma função lambda
, assim como para funções convencionais, algumas
formas são:
- Parâmetros posicionalmente
- Parâmetros nomeadamente
- Parâmetros em lista de tamanho variável(
*args
) - Parâmetros em lista de tamanho variável nomeadamente(
**kwargs
)
Exemplo em cada um dos tipos:
Parâmetros posicionalmente
A forma convencional de passar parâmetros para uma função.
funcao_soma = (lambda x, y: x + y)
print(funcao_soma(1, 2))
# 3
Parâmetros nomeadamente
Outra forma bem comum de se utilizar funções, um pouco mais descritiva, porém ainda simples e bem prático.
funcao_soma = (lambda x, y: x + y)
print(funcao_soma(x=1, y=2)
# 3
Também podemos nomear apenas o segundo parâmetro.
funcao_soma = (lambda x, y: x + y)
print(funcao_soma(1, y=2))
# 3
*args
)
Parâmetros em lista de tamanho variável(Uma forma menos comum, mas útil em alguns casos onde a quantidade de parâmetros são variáveis, por exemplo, a nossa função soma das formas anteriores só somavam dois valores, poderíamos corrigir isso com esse estilo de passagem de parâmetro.
funcao_soma = (lambda *args: sum(args))
print(funcao_soma(1, 2, 3, 4, 5))
# 15
**kwargs
)
Parâmetros em lista de tamanho variável nomeadamente(Forma também não muito utilizada, com exceção de quando se utiliza algum framework de UI
que, em geral, adotam esse
estilo de notação.
É bem útil quando é necessário realizar a distinção dos valores e a função tem uma grande variedade de parâmetros, mas
esse não costuma ser caso de funções lambda
, de qualquer forma essa opção existe e pode ser utilizada.
funcao_soma = (lambda **kwargs: sum(kwargs.values()))
print(funcao_soma(a=1, b=2, c=3))
# 6
Exemplos práticos de bom uso da função lambda em Python
As funções lambda
muitas vezes são deixadas de lado por muitas pessoas, principalmente por não verem bons usos
práticos para elas, mas existem algumas boas formas de se utilizar funções lambda
sem tornar o código completamente
ilegível.
Filtrando valores de uma lista com lambda
Digamos que deseja filtrar uma lista selecionando apenas os valores maiores que 5, isso poderia ser efetuado com a
função filter
e uma simples expressão lambda.
numeros = [1, 9, 20, 3, 41, 50, 0, -5]
print(numeros)
# [1, 9, 20, 3, 41, 50, 0, -5]
numeros = list(filter(lambda x: x > 5, numeros))
print(numeros)
# [9, 20, 41, 50]
Tratando uma lista de valores com lambda
Digamos que tenha uma lista com textos em minúsculos e gostaria da versão capitalizada desse texto, a função map
em conjunto com uma expressão lambda
simples pode ser utilizada para isto.
cores_minusculo = ['azul', 'branco', 'vermelho']
print(cores_minusculo)
# ['azul', 'branco', 'vermelho']
cores_maiusculo = list(map(lambda x: x.upper(), cores_minusculo))
print(cores_maiusculo)
# ['AZUL', 'BRANCO', 'VERMELHO']
Formatando um texto de uma lista de valores com lambda
Caso queira exibir os números separados por um -
, isso também pode ser feito utilizando reduce
e lambda.
from functools import reduce
numeros = [1, 9, 20, 3, 41, 50, 0]
print(numeros)
# [1, 9, 20, 3, 41, 50, 0]
numeros = reduce(lambda x1, x2: f'{x1} - {x2}', numeros)
print(numeros)
# 1 - 9 - 20 - 3 - 41 - 50 - 0
Ordenando uma lista com lambda
Esse é o exemplo onde a função lambda
brilha, sem dúvidas utilizá-la como o parâmetro “key” das funções ordenadores é
uma forma simples e elegante de resolver esse problema
exemplos = ['exemplo1', 'exemplo4',
'exemplo2', 'exemplo33',
'exemplo100', 'exemplo44']
print(exemplos)
# ['exemplo1', 'exemplo4',
# 'exemplo2', 'exemplo33',
# 'exemplo100', 'exemplo44']
exemplos = sorted(exemplos)
print(exemplos)
# ['exemplo1', 'exemplo100',
# 'exemplo2', 'exemplo33',
# 'exemplo4', 'exemplo44']
exemplos = sorted(exemplos,
key=lambda x: int(x.replace('exemplo', '')))
print(exemplos)
# ['exemplo1', 'exemplo2',
# 'exemplo4', 'exemplo33',
# 'exemplo44', 'exemplo100']
Utilização exagerada de funções lambda
Quando comecei a escrever esse artigo queria fazer o mais completo possível, cobrindo todas as possibilidades,
semelhante ao que fiz no artigo sobre dicionários. Quando comecei a pesquisar sobre e ver como os outros
sites e blogs estavam mostrando e ensinando as funções lambdas
mudei de ideia.
As funções lambdas
são ótimas para casos específicos, normalmente expressões simples que cabem numa linha, semelhantes
aos exemplos na seção anterior, mas em alguns tutoriais na internet vi exemplos que estão realmente exagerados e a
utilização de da expressão é completamente desnecessário ou muito exagerado e fora da realidade.
Cheguei a ver exemplos de testes unitários para expressões lambdas, qual a lógica disso? Não seria mais fácil definir uma função normal?
Outra coisa é a utilização de expressão lambda em classes, no PEP 8
diz que deve se evitar associar funções lambda a
variável, porque alguém faria isso dentro de uma classe?
Conclusão
As funções lambda
são e vão ser por natureza extremamente controversa, afinal a razão real delas existirem é para
simplificar a definição de uma função, e isso muitas vezes acaba deixando o código confuso e ilegível.
Cabe a cada programador saber a hora exata de utilizá-las ou não, evitando sempre que isso deixará seu código
desorganizado, afinal, não se esqueça do zen
do Python “bonito é melhor que feio”, e definitivamente expressões
lambda
em excesso e nos locais errados não são bonitas.