Eu uso principalmente funções lambda, mas às vezes uso funções aninhadas que parecem fornecer o mesmo comportamento.
Aqui estão alguns exemplos triviais em que eles fazem funcionalmente a mesma coisa se um deles for encontrado em outra função:
Função lambda
>>> a = lambda x : 1 + x
>>> a(5)
6
Função aninhada
>>> def b(x): return 1 + x
>>> b(5)
6
Existem vantagens em usar um em relação ao outro? (Desempenho? Legibilidade? Limitações? Consistência? Etc.)
Isso importa mesmo? Se não, isso viola o princípio Pythônico:
Deve haver uma - e de preferência apenas uma - maneira óbvia de fazer isso .
lambda
, mas discordo que isso é "muito raro", é comum para funções-chave parasorted
ouitertools.groupby
etc., por exemplosorted(['a1', 'b0'], key= lambda x: int(x[1]))
Na prática, para mim, existem duas diferenças:
A primeira é sobre o que eles fazem e o que eles retornam:
def é uma palavra-chave que não retorna nada e cria um 'nome' no namespace local.
lambda é uma palavra-chave que retorna um objeto de função e não cria um 'nome' no namespace local.
Portanto, se você precisar chamar uma função que recebe um objeto de função, a única maneira de fazer isso em uma linha de código python é com um lambda. Não há equivalente com def.
Em algumas estruturas, isso é bastante comum; por exemplo, eu uso muito o Twisted e faço algo como
é bastante comum e mais conciso com lambdas.
A segunda diferença é sobre o que a função real pode fazer.
Por exemplo,
funciona como esperado, enquanto
é um SyntaxError.
Claro, existem soluções alternativas - substitua
print
comsys.stdout.write
, ouimport
com__import__
. Mas geralmente é melhor você ir com uma função nesse caso.fonte
Nesta entrevista, Guido van Rossum diz que gostaria de não ter deixado 'lambda' em Python:
IMHO, Iambdas pode ser conveniente às vezes, mas geralmente são convenientes em detrimento da legibilidade. Você pode me dizer o que isso faz:
Eu escrevi e levei um minuto para descobrir. Isto é do Projeto Euler - não direi qual é o problema porque odeio spoilers, mas ele roda em 0,124 segundos :)
fonte
lambda
não ser removido no 3.0 era algo próximo, e que Guido não estava lutando para mantê-lo.Para n = 1000, aqui está algum tempo para chamar uma função versus um lambda:
fonte
Atuação:
Criar uma função com
lambda
é um pouco mais rápido do que criá-la comdef
. A diferença se deve àdef
criação de uma entrada de nome na tabela de locais. A função resultante tem a mesma velocidade de execução.Legibilidade:
As funções Lambda são um pouco menos legíveis para a maioria dos usuários de Python, mas também muito mais concisas em algumas circunstâncias. Considere a conversão de uma rotina não funcional para uma rotina funcional:
Como você pode ver, a
lambda
versão é mais curta e "mais fácil" no sentido de que você só precisa adicionarlambda v:
à versão não funcional original para converter para a versão funcional. Também é muito mais conciso. Mas lembre-se, muitos usuários de Python ficarão confusos com a sintaxe lambda, então o que você perde em comprimento e complexidade real pode ser recuperado na confusão de outros desenvolvedores.Limitações:
lambda
as funções só podem ser usadas uma vez, a menos que sejam atribuídas a um nome de variável.lambda
funções atribuídas a nomes de variáveis não têm vantagem sobredef
funções.lambda
funções podem ser difíceis ou impossíveis de conservar.def
os nomes das funções devem ser cuidadosamente escolhidos para serem razoavelmente descritivos e únicos ou, pelo menos, não utilizados em seu escopo.Consistência:
Python principalmente evita convenções de programação funcional em favor de semânticas objetivas mais simples e procedurais. O
lambda
operador está em contraste direto com esse viés. Além disso, como uma alternativa ao já predominantedef
, alambda
função adiciona diversidade à sua sintaxe. Alguns considerariam isso menos consistente.Funções pré-existentes:
Conforme observado por outros, muitos usos de
lambda
no campo podem ser substituídos por membros dooperator
ou de outros módulos. Por exemplo:O uso da função pré-existente pode tornar o código mais legível em muitos casos.
O princípio pitônico: "Deve haver uma - e de preferência apenas uma - maneira óbvia de fazer isso"
Isso é semelhante à doutrina da fonte única da verdade . Infelizmente, o princípio da única maneira óbvia de fazer isso sempre foi mais uma aspiração melancólica para Python, em vez de um verdadeiro princípio orientador. Considere as abrangências de array muito poderosas em Python. Eles são funcionalmente equivalentes às funções
map
efilter
:lambda
edef
são iguais.É uma questão de opinião, mas eu diria que qualquer coisa na linguagem Python destinada ao uso geral que obviamente não quebra nada é "Pythônico" o suficiente.
fonte
Há uma vantagem em usar um lambda em vez de uma função regular: eles são criados em uma expressão.
Existem várias desvantagens:
'<lambda>'
)Eles também são o mesmo tipo de objeto. Por esses motivos, geralmente prefiro criar funções com a
def
palavra - chave em vez de lambdas.Primeiro ponto - eles são o mesmo tipo de objeto
Um lambda resulta no mesmo tipo de objeto que uma função regular
Como lambdas são funções, eles são objetos de primeira classe.
Lambdas e funções:
Mas lambdas estão, por padrão, perdendo algumas coisas que as funções obtêm por meio da sintaxe de definição de função completa.
Um lamba
__name__
é'<lambda>'
Afinal, lambdas são funções anônimas, então eles não sabem o próprio nome.
Portanto, lambda's não podem ser pesquisados programaticamente em seu namespace.
Isso limita certas coisas. Por exemplo,
foo
pode ser pesquisado com código serializado, enquantol
não pode:Podemos pesquisar
foo
muito bem - porque ele conhece seu próprio nome:Lambdas não têm anotações nem docstring
Basicamente, lambdas não são documentados. Vamos reescrever
foo
para ser melhor documentado:Agora, foo tem documentação:
Considerando que, não temos o mesmo mecanismo para fornecer as mesmas informações para lambdas:
Mas podemos hackea-los:
Porém, provavelmente há algum erro atrapalhando a saída da ajuda.
Lambdas só pode retornar uma expressão
Lambdas não podem retornar declarações complexas, apenas expressões.
As expressões podem ser bastante complexas e, se você tentar muito, provavelmente conseguirá o mesmo com um lambda, mas a complexidade adicionada é mais prejudicial à escrita de código claro.
Usamos Python para maior clareza e facilidade de manutenção. O uso excessivo de lambdas pode funcionar contra isso.
A única vantagem para lambdas: pode ser criado em uma única expressão
Esta é a única vantagem possível. Já que você pode criar um lambda com uma expressão, você pode criá-lo dentro de uma chamada de função.
Criar uma função dentro de uma chamada de função evita a pesquisa de nome (barata) em comparação com uma criada em outro lugar.
No entanto, como o Python é avaliado estritamente, não há outro ganho de desempenho em fazer isso além de evitar a consulta de nome.
Para uma expressão muito simples, posso escolher um lambda.
Eu também tendo a usar lambdas ao fazer Python interativo, para evitar várias linhas quando uma delas faz. Eu uso o seguinte tipo de formato de código quando quero passar um argumento para um construtor ao chamar
timeit.repeat
:E agora:
Acredito que a ligeira diferença de tempo acima pode ser atribuída à pesquisa de nome em
return_nullary_function
- observe que é muito insignificante.Conclusão
Lambdas são bons para situações informais em que você deseja minimizar linhas de código em favor de fazer um ponto singular.
Lambdas são ruins para situações mais formais em que você precisa de clareza para editores de código que virão mais tarde, especialmente nos casos em que não são triviais.
Sabemos que devemos dar bons nomes aos nossos objetos. Como podemos fazer isso quando o objeto não tem nome?
Por todos esses motivos, geralmente prefiro criar funções com em
def
vez de comlambda
.fonte
Eu concordo com o conselho de nosklo: se você precisar dar um nome à função, use
def
. Reservolambda
funções para casos em que estou apenas passando um breve trecho de código para outra função, por exemplo:fonte
Embora concorde com as outras respostas, às vezes é mais legível. Aqui está um exemplo que
lambda
é útil, em um caso de uso que sempre encontro de N dimensionaldefaultdict
.Aqui está um exemplo:
Acho mais legível do que criar um
def
para a segunda dimensão. Isso é ainda mais significativo para dimensões superiores.fonte
from functools import partial; defaultdict(partial(defaultdict, list))
. Atribua parcial a um nome se quiser usá-lo mais de uma vez. Mas, se você continuar encontrando essa construção, significa que você não é SECO. Fatore em uma biblioteca de utilitários. Você pode usar essa construção para criar um defaultdict arbitrário n-dimensional usando outras functools (ou um loop ou recursão).O uso principal de lambda sempre foi para funções de retorno de chamada simples e para mapear, reduzir, filtrar, que requerem uma função como argumento. Com as compreensões de lista se tornando a norma, e o acréscimo permitido se como em:
é difícil imaginar um caso real para o uso de lambda no uso diário. Como resultado, eu diria, evite lambda e crie funções aninhadas.
fonte
Uma limitação importante dos lambdas é que eles não podem conter nada além de uma expressão. É quase impossível para uma expressão lambda produzir qualquer coisa além de efeitos colaterais triviais, uma vez que ela não pode ter um corpo tão rico quanto uma
def
função 'ed.Dito isso, Lua influenciou meu estilo de programação no sentido do uso extensivo de funções anônimas e eu amontoei meu código com elas. Além disso, tendo a pensar em mapear / reduzir como operadores abstratos de maneiras que não considero compreensões de lista ou geradores, quase como se estivesse adiando uma decisão de implementação explicitamente usando esses operadores.
Edit: Esta é uma questão muito antiga, e minhas opiniões sobre o assunto mudaram um pouco.
Em primeiro lugar, sou fortemente contra atribuir uma
lambda
expressão a uma variável; já que python tem uma sintaxe especial apenas para isso (dica,def
). Além disso, muitos dos usos de lambda, mesmo quando não recebem um nome, têm implementações predefinidas (e mais eficientes). Por exemplo, o exemplo em questão pode ser abreviado para apenas(1).__add__
, sem a necessidade de envolvê-lo emlambda
oudef
. Muitos outros usos comuns pode ser satisfeita com alguma combinação dasoperator
,itertools
efunctools
módulos.fonte
(1).__add__
- chamar métodos dunder diretamente quase nunca deve acontecer. Millambda
s para cada chamada direta de Dunder.(1).__add__
são um tanto incomuns, mas eu não chegaria perto de "deveria". sem dúvida, acho o primeiro muito mais legívellambda x: 1 + x
. Se tivéssemos algo mais parecido com a notação de fatia haskells,(1+)
isso seria ótimo, mas temos que nos contentar com o que é semanticamente exatamente essa coisa, o nome do método dunder.Considerando um exemplo simples,
fonte
Se você for apenas atribuir o lambda a uma variável no escopo local, você também pode usar def porque é mais legível e pode ser expandido mais facilmente no futuro:
ou
fonte
from operator import pow;map(pow, someList)
e(a**b for a,b in someList)
são ainda mais legíveis.Um uso para lambdas que encontrei ... é em mensagens de depuração.
Como lambdas podem ser avaliados lentamente, você pode ter um código como este:
em vez de possivelmente caro:
que processa a string de formato mesmo se a chamada de depuração não produzir saída devido ao nível de registro atual.
Obviamente, para que funcione conforme descrito, o módulo de registro em uso deve suportar lambdas como "parâmetros preguiçosos" (como meu módulo de registro faz).
A mesma ideia pode ser aplicada a qualquer outro caso de avaliação preguiçosa para criação de valor de conteúdo on demand.
Por exemplo, este operador ternário personalizado:
ao invés de:
com lambdas apenas a expressão selecionada pela condição será avaliada, sem lambdas ambos serão avaliados.
É claro que você poderia simplesmente usar funções em vez de lambdas, mas para expressões curtas lambdas são (c) mais enxutos.
fonte
logging
já tem formatação lenta:log.debug("this is my message: %r", some_data)
só formatará quando / se a mensagem for solicitada.some_data
pode ser uma expressão cara ou chamada de função / método.Eu concordo com nosklo. A propósito, mesmo com uma função use uma vez, jogue fora , na maioria das vezes você quer apenas usar algo do módulo de operação.
POR EXEMPLO :
Você tem uma função com esta assinatura: myFunction (data, callback function).
Você quer passar uma função que adiciona 2 elementos.
Usando lambda:
A maneira pítônica:
Ou, claro, este é um exemplo simples, mas há muitas coisas que o módulo do operador fornece, incluindo os itens setters / getters para list e dict. Realmente legal.
fonte
A principal diferença é que você não pode usar
def
funções embutidas, o que é, em minha opinião, o caso de uso mais conveniente para umalambda
função. Por exemplo, ao classificar uma lista de objetos:Eu sugeriria, portanto, manter o uso de lambdas para esse tipo de operação trivial, que também não se beneficia muito da documentação automática fornecida ao nomear a função.
fonte
lambda é útil para gerar novas funções:
fonte