Por que as lambdas do Python são úteis? [fechadas]

929

Estou tentando descobrir lambdas em Python. O lambda é um daqueles itens de linguagem "interessantes" que na vida real devem ser esquecidos?

Tenho certeza de que há alguns casos extremos nos quais isso pode ser necessário, mas, dada a obscuridade, o potencial de ser redefinido em versões futuras (minha suposição com base nas várias definições) e a clareza de codificação reduzida - caso isso ocorra ser evitado?

Isso me lembra transbordar (buffer overflow) dos tipos C - apontando para a variável superior e sobrecarregando para definir os outros valores de campo. Parece uma espécie de espetáculo técnico, mas um pesadelo para os codificadores de manutenção.

meade
fonte
261
+1 Boa pergunta - suposições ruins (obscuridade do lambda) =) Tente não julgar as técnicas de programação. Avalie-os e adicione-os ao seu kit de ferramentas mentais. Se você não gosta deles, não os use e esteja preparado para discuti-los logicamente sem se tornar religioso.
Kieveli 23/02/10
41
Regras de Haskell! As funções Lambda oferecem expressividade e poder de abstração.
Jonathan Barbero
11
@JAL Sem mencionar o LISP ...
ApproachingDarknessFish
8
@ApproachingDarknessFish "Ah, esse é o parêntese do seu pai. Uma arma mais civilizada de uma era mais civilizada." - Obi Lisp Kenobi
Campos

Respostas:

1009

Você está falando sobre funções lambda ? Gostar

lambda x: x**2 + 2*x - 5

Essas coisas são realmente bastante úteis. O Python suporta um estilo de programação chamado programação funcional, onde você pode passar funções para outras funções para fazer coisas. Exemplo:

mult3 = filter(lambda x: x % 3 == 0, [1, 2, 3, 4, 5, 6, 7, 8, 9])

define mult3como [3, 6, 9], os elementos da lista original que são múltiplos de 3. Isso é mais curto (e, pode-se argumentar, mais claro) do que

def filterfunc(x):
    return x % 3 == 0
mult3 = filter(filterfunc, [1, 2, 3, 4, 5, 6, 7, 8, 9])

Obviamente, nesse caso em particular, você poderia fazer o mesmo que uma compreensão de lista:

mult3 = [x for x in [1, 2, 3, 4, 5, 6, 7, 8, 9] if x % 3 == 0]

(ou mesmo como range(3,10,3)), mas existem muitos outros casos de uso mais sofisticados nos quais você não pode usar uma compreensão de lista e uma função lambda pode ser a maneira mais curta de escrever algo.

  • Retornando uma função de outra função

    >>> def transform(n):
    ...     return lambda x: x + n
    ...
    >>> f = transform(3)
    >>> f(4)
    7

    Isso geralmente é usado para criar wrappers de função, como os decoradores do Python.

  • Combinando elementos de uma sequência iterável com reduce()

    >>> reduce(lambda a, b: '{}, {}'.format(a, b), [1, 2, 3, 4, 5, 6, 7, 8, 9])
    '1, 2, 3, 4, 5, 6, 7, 8, 9'
  • Classificando por uma chave alternativa

    >>> sorted([1, 2, 3, 4, 5, 6, 7, 8, 9], key=lambda x: abs(5-x))
    [5, 4, 6, 3, 7, 2, 8, 1, 9]

Eu uso funções lambda regularmente. Demorei um pouco para me acostumar com eles, mas acabei percebendo que eles são uma parte muito valiosa da linguagem.

David Z
fonte
26
Ame os exemplos, muito fáceis de entender. Mas para a parte de redução. Se eu tiver que implementar esse recurso. Eu faria','.join(str(x) for x in [1,2,3,4,5,6,7,8,9])
etlds 30/08
3
BTW, se você executar isso no Python3, precisará chamar a lista nos resultados do filtro para ver os valores reais, além de importar a redução de functools
Gerard
Temos certeza da definição de "programação funcional" acima? Foi um pouco confuso para mim.
Stdout
3
Eu acho que o ponto principal é que as lambdafunções podem ser anônimas (como estão em todos os seus exemplos). Se você está atribuindo uma lambdafunção a qualquer coisa, então você está fazendo errado e deve usar defem vez
Chris_Rands
1
@zgulser Não é uma definição, é apenas uma declaração sobre algo que a programação funcional permite que você faça.
David Z
377

lambdaé apenas uma maneira elegante de dizer function. Além do nome, não há nada obscuro, intimidador ou enigmático. Ao ler a seguinte linha, substitua lambdapor function:

>>> f = lambda x: x + 1
>>> f(3)
4

Apenas define uma função de x. Algumas outras línguas, como R, dizem explicitamente:

> f = function(x) { x + 1 }
> f(3)
4

Entende? É uma das coisas mais naturais a se fazer em programação.

user251650
fonte
36
Esta é uma ótima descrição para quem vem de contextos que não são de programação (ou seja: ciências exatas), o que torna o significado de lambda muito simples de entender. Obrigado!
Gabriel
10
Raymond Hettinger lamentou o nome em uma de suas palestras e disse que toda confusão poderia ter sido evitada com o nome de 'make function' em vez de 'lambda'. :-)
ankush981
10
substituir lambdapor functionem sua mente e adicionar returnantes da última expressão
Ciprian Tomoiagă
4
@AaronMcMillin Try type(lambda x: 3). lambdaexpressões e definstruções geram functionobjetos; é apenas a sintaxe de uma lambdaexpressão que limita quais instâncias ela pode produzir.
chepner
6
@AaronMcMillin Você está perdendo o meu argumento. Só porque você não pode definir todas as funções com uma lambdaexpressão não significa que o resultado de uma lambdaexpressão não seja uma função.
chepner
107

O resumo de duas linhas:

  1. Encerramentos : Muito úteis. Aprenda-os, use-os, ame-os.
  2. Palavra- lambdachave do Python : desnecessária, ocasionalmente útil. Se você estiver fazendo algo remotamente complexo com ela, guarde-a e defina uma função real.
John Fouhy
fonte
72

Um lambda é parte de um mecanismo de abstração muito importante que lida com funções de ordem superior. Para obter um entendimento adequado de seu valor, assista às lições de alta qualidade de Abelson e Sussman e leia o livro SICP

Essas são questões relevantes nos negócios modernos de software e cada vez mais populares.

egaga
fonte
1
As expressões lambda estão se tornando populares em outros idiomas (como C #) também. Eles não vão a lugar algum. Ler sobre os fechamentos seria um exercício útil para entender Lambdas. Os fechamentos possibilitam muita magia de codificação em estruturas como o jQuery.
21119 Dan Esparza
3
Não confunda se lambdafunções de primeira classe. Python tem uma lambdadeclaração extremamente limitada , mas possui funções totalmente de primeira classe. A única diferença que faz é que você precisa nomear as funções que deseja transmitir.
Gareth Latty
59

lambdas são extremamente úteis na programação da GUI. Por exemplo, digamos que você esteja criando um grupo de botões e que deseja usar um único retorno de chamada paramaterizado em vez de um retorno de chamada único por botão. O Lambda permite fazer isso com facilidade:

for value in ["one","two","three"]:
    b = tk.Button(label=value, command=lambda arg=value: my_callback(arg))
    b.pack()

(Nota: embora esta pergunta esteja especificamente perguntando lambda, você também pode usar functools.partial para obter o mesmo tipo de resultado)

A alternativa é criar um retorno de chamada separado para cada botão, o que pode levar à duplicação do código.

Bryan Oakley
fonte
1
É exatamente por isso que procurei o que era lambda, mas por que isso funciona, para mim parece exatamente o mesmo que chamar a função diretamente ( stackoverflow.com/questions/3704568/… ). Talvez seja tarde, funciona, mas por que funciona?
RQomey
5
@Rqomey: a diferença é que neste exemplo valueé definido em um loop; no outro exemplo, o parâmetro sempre teve apenas um valor. Quando você adiciona algo como arg=value, está anexando o valor atual ao retorno de chamada. Sem ele, você vincula uma referência à variável no retorno de chamada. A referência sempre conterá o valor final da variável, pois o retorno de chamada ocorre algum tempo depois que o loop já terminou a execução.
Bryan Oakley
1
Acabei de fazer isso funcionar ontem, honestamente, não posso acreditar no quão útil é ... Posso criar um menu a partir de um para loop e um arquivo csv para configuração. Coisas realmente úteis.
Rqomey
1
Observe a existência do functools.partial()que permite fazer isso com menos sujeira (e sem lambda).
Gareth Latty
2
partial(my_callback, value)vs lambda arg=value: my_callback(arg)- o lambda tem muito mais cruft (atribuição ao arg e depois uso) e fica menos claro qual é a intenção (você pode estar fazendo algo sutilmente diferente no lambda). As importações não são realmente um problema (você tem uma pilha de qualquer maneira e é uma vez por arquivo). O código é melhor julgado pelo quão bem ele lê e partial()é muito mais fácil de ler do que o lambda.
amigos estão dizendo sobre
58

Duvido que lambda vá embora. Veja o post de Guido sobre finalmente desistir de tentar removê-lo. Veja também um esboço do conflito .

Você pode conferir esta postagem para obter mais informações sobre o negócio por trás dos recursos funcionais do Python: http://python-history.blogspot.com/2009/04/origins-of-pythons-functional-features.html

Curiosamente, o mapa, o filtro e as funções reduzidas que originalmente motivaram a introdução do lambda e outros recursos funcionais foram em grande parte substituídos pela compreensão da lista e pelas expressões geradoras. De fato, a função de redução foi removida da lista de funções internas no Python 3.0. (No entanto, não é necessário enviar reclamações sobre a remoção do lambda, mapa ou filtro: eles estão ficando. :-)

Meus dois centavos: Raramente o lambda vale tanto quanto a clareza. Geralmente, há uma solução mais clara que não inclui lambda.

rhettg
fonte
2
observe que a redução ainda é importável no Python 3.0. Se você realmente quer, ainda pode tê-lo.
Paweł Polewicz
Eu acho que a tentativa de Guido foi mais sobre a sintaxe. Esta pessoa também pensa que: cackhanded.com/blog/post/2008/01/24/…
leewz
38

No Python, lambdaé apenas uma maneira de definir funções embutidas,

a = lambda x: x + 1
print a(1)

e..

def a(x): return x + 1
print a(1)

..é exatamente o mesmo.

Não há nada que você possa fazer com o lambda que você não possa fazer com uma função regular - as funções do Python são um objeto como qualquer outra coisa, e os lambdas simplesmente definem uma função:

>>> a = lambda x: x + 1
>>> type(a)
<type 'function'>

Sinceramente, acho que a lambdapalavra-chave é redundante no Python - nunca tive a necessidade de usá-las (ou vi uma usada onde uma função regular, uma compreensão de lista ou uma das muitas funções incorporadas poderiam ser melhor utilizadas)

Para um exemplo completamente aleatório, do artigo "O lambda do Python está quebrado!" :

Para ver como o lambda está quebrado, tente gerar uma lista de funções em fs=[f0,...,f9]que fi(n)=i+n. Primeira tentativa:

>>> fs = [(lambda n: i + n) for i in range(10)]
>>> fs[3](4)
13

Eu diria que, mesmo que isso funcionasse, é horrível e "não-tônico", a mesma funcionalidade poderia ser escrita de inúmeras outras maneiras, por exemplo:

>>> n = 4
>>> [i + n for i in range(10)]
[4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

Sim, não é a mesma coisa, mas nunca vi uma causa em que a geração de um grupo de funções lambda em uma lista fosse necessária. Pode fazer sentido em outras linguagens, mas Python não é Haskell (ou Lisp, ou ...)

Observe que podemos usar o lambda e ainda alcançar os resultados desejados desta maneira:

>>> fs = [(lambda n,i=i: i + n) for i in range(10)]
>>> fs[3](4)
7

Editar:

Existem alguns casos em que o lambda é útil, por exemplo, geralmente é conveniente ao conectar sinais em aplicativos PyQt, como este:

w = PyQt4.QtGui.QLineEdit()
w.textChanged.connect(lambda event: dothing())

Apenas fazer w.textChanged.connect(dothing)chamaria o dothingmétodo com um eventargumento extra e causaria um erro. Usar o lambda significa que podemos descartar o argumento de maneira organizada sem precisar definir uma função de quebra automática.

dbr
fonte
2
seu argumento "lambda is broken" está quebrado, porque as regras de escopo da variável python funcionam dessa maneira, ponto final. Você será mordido da mesma maneira se tiver criado um fechamento dentro do loop for.
Antti Haapala 27/02
1
O lambda é apenas uma maneira de o python fornecer ao usuário uma função "anônima", como muitas outras linguagens (por exemplo, javascript).
Stefan Gruenwald
1
O lambda e a função aque você definiu não são exatamente os mesmos. :) Eles diferem em __name__campo, pelo menos ...
nperson325681
1
Funciona mais do que apenas uma função embutida.
Kta #
Seu argumento sobre "pode ​​fazer sentido em outro idioma" é estranho. Ou existem qualidades intrínsecas às lambdas, ou não.
Titou 02/02
31

Acho o lambda útil para uma lista de funções que fazem o mesmo, mas para circunstâncias diferentes.

Como as regras plurais do Mozilla :

plural_rules = [
    lambda n: 'all',
    lambda n: 'singular' if n == 1 else 'plural',
    lambda n: 'singular' if 0 <= n <= 1 else 'plural',
    ...
]
# Call plural rule #1 with argument 4 to find out which sentence form to use.
plural_rule[1](4) # returns 'plural'

Se você tivesse que definir uma função para todos, ficaria louco até o final.
Além disso, não seria bom com nomes de funções como plural_rule_1, plural_rule_2etc. E você precisaria eval()disso quando depender de um ID de função variável.

Tor Valamo
fonte
1
Isso se parece com os breves encontros que tive até agora em F # com correspondência de padrões e opções. Você tem mais informações sobre como usar esta sintaxe?
Ken
26

Praticamente tudo o que você pode fazer lambdapode ser melhor com funções nomeadas ou expressões de lista e gerador.

Consequentemente, na maioria das vezes você deve apenas um daqueles em praticamente qualquer situação (exceto, talvez, pelo código de rascunho escrito no intérprete interativo).

Aaron Maenpaa
fonte
3
"na maioria das vezes você deve apenas um daqueles em basicamente qualquer situação" Período. Digitar lambda no intérprete não é tão útil.
S.Lott 20/05/09
11
@Javier Concordo com você se você está falando sobre "lambda" o conceito; no entanto, se estamos falando de "lambda", a palavra-chave python: 1) as funções nomeadas são mais rápidas e podem fazer mais (declarações + expressões) em quase qualquer lugar em que você usaria lambdas (mapa + filtro), basta gerar expressões ou listar compreensões que são mais eficientes e concisos. Não estou dizendo que funções de primeira classe não sejam legais, apenas que a palavra-chave "lambda" em python não é tão boa quanto usar uma função nomeada, só isso.
Aaron Maenpaa
3
lambda tem sido indispensável para me para uso com funções que recebem argumentos de retorno de chamada como a chave = argumento para sort () e ordenados ()
Rick Copeland
19
@ Rick Não duvido disso, mas a realidade é que, quando você vê "lambda" e pensa "zohmygod lambda" e começa a escrever o código do esquema em python, certamente ficará decepcionado com as limitações da expressão lambda do python. Por outro lado, se você começar a pensar consigo mesmo "A compreensão da lista funcionará? Não. O que eu preciso me beneficiar de ser uma função nomeada? Não. Tudo bem, tudo bem: classificado (xs, key = lambda x: x.name, x.height) ", você provavelmente acabará usando lambda o número certo de vezes.
Aaron Maenpaa
4
+1: Não posso enfatizar isso o suficiente quando se usa um lambda, se usa uma função sem nome . E os nomes têm um valor agregado intelectual precioso .
Stephane Rolland
19

Uso Python há alguns anos e nunca me deparei com um caso em que precisei de lambda. Realmente, como o tutorial afirma, é apenas para açúcar sintático.

Matt Schmidt
fonte
8
Eles são muito úteis ao desenvolver uma GUI usando python. Geralmente, os widgets precisam de uma referência a uma função. Se você precisar de um widget para chamar uma função e passar argumentos, o lambda é uma maneira muito conveniente de fazer isso.
Bryan Oakley
1
Qual é a vantagem de passar vários argumentos para a função? func_name (a, b): regresso a + b em vez de usar lambda
dter
2
não é necessário, mas ajuda a escrever um código mais curto e mais legível em muitos casos, esp. em linguagens detalhado como Java ou C ++
phuclv
17

Não posso falar com a implementação específica do lambda em python, mas, em geral, as funções lambda são realmente úteis. Eles são uma técnica central (talvez até a técnica) de programação funcional e também são muito úteis em programas orientados a objetos. Para certos tipos de problemas, eles são a melhor solução, portanto, certamente não devem ser esquecidos!

Sugiro que você leia sobre os fechamentos e a função map (que se vincula aos documentos python, mas existe em quase todas as linguagens que suportam construções funcionais) para ver por que é útil.

rmeador
fonte
3
Esse material pode ser feito sem lambdas. É apenas um grande aborrecimento.
2027 Brian
17

Função Lambda é uma maneira não-burocrática de criar uma função.

É isso aí. Por exemplo, suponhamos que você tenha sua função principal e precise quadrado dos valores. Vamos ver a maneira tradicional e a maneira lambda de fazer isso:

Caminho tradicional:

def main():
...
...
y = square(some_number)
...
return something

def square(x):
    return x**2

A maneira lambda:

def main():
...
square = lambda x: x**2
y = square(some_number)
return something

Veja a diferença?

As funções do Lambda vão muito bem com listas, como compreensão de listas ou mapa. De fato, a compreensão da lista é uma maneira "pitônica" de se expressar usando lambda. Ex:

>>>a = [1,2,3,4]
>>>[x**2 for x in a]
[1,4,9,16]

Vamos ver o que cada elemento da sintaxe significa:

[]: "Me dê uma lista"

x ** 2: "usando esta função recém-nascida"

para x em um: "em cada elemento em um"

Isso é conveniente? Criando funções como esta. Vamos reescrevê-lo usando lambda:

>>> square = lambda x: x**2
>>> [square(s) for x in a]
[1,4,9,16]

Agora vamos usar o mapa, que é a mesma coisa, mas mais neutro em termos de idioma. O Maps usa dois argumentos:

(i) uma função

(ii) um iterável

E fornece uma lista na qual cada elemento é a função aplicada a cada elemento do iterável.

Então, usando o mapa, teríamos:

>>> a = [1,2,3,4]
>>> squared_list = map(lambda x: x**2, a)

Se você dominar lambdas e mapeamento, terá um grande poder de manipular dados de maneira concisa. As funções do Lambda não são obscuras nem tiram a clareza do código. Não confunda algo difícil com algo novo. Depois de começar a usá-los, você ficará bem claro.

Lucas Ribeiro
fonte
13

Uma das coisas boas sobre lambdaisso, na minha opinião, é discreta: é uma maneira de adiar uma avaliação para formulários simples até que o valor seja necessário. Deixe-me explicar.

Muitas rotinas de biblioteca são implementadas para permitir que determinados parâmetros sejam chamados (dos quais lambda é um). A idéia é que o valor real será calculado apenas no momento em que será usado (e não quando for chamado). Um exemplo (artificial) pode ajudar a ilustrar o ponto. Suponha que você tenha uma rotina que registraria um determinado registro de data e hora. Você deseja que a rotina use o horário atual menos 30 minutos. Você chamaria assim

log_timestamp(datetime.datetime.now() - datetime.timedelta(minutes = 30))

Agora, suponha que a função real seja chamada apenas quando ocorrer um determinado evento e você deseja que o carimbo de data e hora seja calculado apenas nesse momento. Você pode fazer isso assim

log_timestamp(lambda : datetime.datetime.now() - datetime.timedelta(minutes = 30))

Supondo que a log_timestamplata possa manipular chamadas de chamada como essa, ela avaliará isso quando precisar e você receberá o carimbo de data / hora nesse momento.

É claro que existem maneiras alternativas de fazer isso (usando o operatormódulo, por exemplo), mas espero ter transmitido o ponto.

Atualização : Aqui está um exemplo do mundo real um pouco mais concreto.

Atualização 2 : Eu acho que este é um exemplo do que é chamado de thunk .

Noufal Ibrahim
fonte
11

Como mencionado acima, o operador lambda no Python define uma função anônima e, no Python, as funções são encerramentos. É importante não confundir o conceito de fechamento com o operador lambda, que é meramente metadona sintática para eles.

Quando eu comecei no Python, há alguns anos, usei muito lambdas, pensando que eram legais, juntamente com a compreensão da lista. No entanto, escrevi e tenho que manter um grande site escrito em Python, da ordem de vários milhares de pontos de função. Aprendi por experiência própria que os lambdas podem ser bons para prototipar as coisas, mas não oferecem nada sobre funções embutidas (encerramentos nomeados), exceto para salvar alguns toques de tecla, ou às vezes não.

Basicamente, isso se resume a vários pontos:

  • é mais fácil ler softwares escritos explicitamente usando nomes significativos. Os fechamentos anônimos por definição não podem ter um nome significativo, pois não têm nome. Essa brevidade parece, por algum motivo, também infectar parâmetros lambda; portanto, vemos frequentemente exemplos como lambda x: x + 1
  • é mais fácil reutilizar os fechamentos nomeados, pois eles podem ser referidos pelo nome mais de uma vez, quando houver um nome ao qual eles possam se referir.
  • é mais fácil depurar o código que está usando fechamentos nomeados em vez de lambdas, porque o nome aparecerá em tracebacks e em torno do erro.

Isso é motivo suficiente para reuni-los e convertê-los em fechamentos nomeados. No entanto, tenho dois outros rancores contra fechamentos anônimos.

O primeiro rancor é simplesmente o fato de serem apenas mais uma palavra-chave desnecessária que atravessa o idioma.

O segundo rancor é mais profundo e no nível do paradigma, ou seja, eu não gosto que eles promovam um estilo de programação funcional, porque esse estilo é menos flexível que os estilos de passagem de mensagem, orientada a objetos ou procedimentais, porque o cálculo lambda não é de Turing. complete (felizmente em Python, ainda podemos romper essa restrição mesmo dentro de uma lambda). As razões pelas quais sinto que as lambdas promovem esse estilo são:

  • Há um retorno implícito, ou seja, eles parecem que "deveriam" ser funções.

  • Eles são um mecanismo alternativo de ocultação de estado para outro mecanismo mais explícito, mais legível, mais reutilizável e mais geral: métodos.

Tento muito escrever Python sem lambda e removê-las à vista. Eu acho que Python seria uma linguagem um pouco melhor sem lambdas, mas essa é apenas a minha opinião.

Mike A
fonte
1
"... em funções Python são fechamentos". Isso não está certo, pelo que entendi. Encerramentos são funções, mas nem sempre são funções. Função-> lambda x, y: x + y. Closure-> lambda x: lambda y: x + y
0atman
6
"porque o cálculo lambda não é completo de Turing" está totalmente errado, o cálculo lambda não tipado é Turing completo, essa é a razão pela qual é tão significativo. Você pode obter recursão usando o Y-Combinator,Y = lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args)))
Antti Haapala
Além disso, se alguém vai à Wikipedia para ler sobre a integridade de Turing, diz "Um exemplo clássico é o cálculo lambda".
Antti Haapala 27/02
a sério - Não é Turing completo - essa resposta precisa de uma edição ou retração séria.
Tony Suffolk 66
@ MarcinŁoś Up-vote porque adere ao KISS. Como comparação, o livro da K&R menciona que, embora o uso da atribuição como parte ou uma expressão maior seja mais compacto, geralmente é menos legível. A tendência de usar padrões de programação funcional é banal e clichê. É suficiente afirmar como eles podem ser usados, mas é excessivamente zeloso afirmar que eles são fundamentais para se tornar um desenvolvedor competente; completamente subjetivo. Esse argumento é análogo aos desenvolvedores de C ++ que argumentam que linguagens sem classes são primitivas, inferiores e inadequadas. "Turing-completeness", argumentos são pedantes.
typedeaf
11

Na verdade, os lambdas são construções muito poderosas que derivam de idéias em programação funcional, e é algo que nunca será facilmente revisado, redefinido ou removido no futuro próximo do Python. Eles ajudam a escrever um código mais poderoso, pois permite passar funções como parâmetros, assim, a idéia de funções como cidadãos de primeira classe.

As lambdas tendem a ficar confusas, mas depois que um entendimento sólido é obtido, você pode escrever um código limpo e elegante como este:

squared = map(lambda x: x*x, [1, 2, 3, 4, 5])

A linha de código acima retorna uma lista dos quadrados dos números na lista. Claro, você também pode fazê-lo como:

def square(x):
    return x*x

squared = map(square, [1, 2, 3, 4, 5])

É óbvio que o código anterior é mais curto, e isso é especialmente verdadeiro se você pretende usar a função map (ou qualquer função semelhante que utilize uma função como parâmetro) em apenas um local. Isso também torna o código mais intuitivo e elegante.

Além disso, como @David Zaslavsky mencionou em sua resposta, a compreensão da lista nem sempre é o caminho a percorrer, especialmente se sua lista precisa obter valores de alguma maneira matemática obscura.

Do ponto de vista mais prático, uma das maiores vantagens das lambdas para mim recentemente foi na GUI e na programação orientada a eventos. Se você der uma olhada nos retornos de chamada no Tkinter, todos eles tomam como argumentos o evento que os acionou. Por exemplo

def define_bindings(widget):
    widget.bind("<Button-1>", do-something-cool)

def do-something-cool(event):
    #Your code to execute on the event trigger

Agora, e se você tivesse alguns argumentos para passar? Algo tão simples como passar 2 argumentos para armazenar as coordenadas de um clique do mouse. Você pode facilmente fazer assim:

def main():
    # define widgets and other imp stuff
    x, y = None, None
    widget.bind("<Button-1>", lambda event: do-something-cool(x, y))

def do-something-cool(event, x, y):
    x = event.x
    y = event.y
    #Do other cool stuff

Agora você pode argumentar que isso pode ser feito usando variáveis ​​globais, mas você quer realmente se preocupar com gerenciamento de memória e vazamento, especialmente se a variável global for usada apenas em um local específico? Isso seria apenas um estilo de programação ruim.

Em resumo, as lambdas são impressionantes e nunca devem ser subestimadas. Os lambdas Python não são os mesmos que os lambdas LISP (que são mais poderosos), mas você pode realmente fazer muitas coisas mágicas com eles.

varagrawal
fonte
Obrigado. Eu não entendi completamente o seu último exemplo. Como x e y são definidos em ambos maine do_something_cool? O que acontece com xe yna função? Os valores passados ​​parecem ser imediatamente substituídos? Como a função conhece event? Você poderia adicionar alguns comentários / explicações? Obrigado
Sanjay Manohar
@SanjayManohar Estou passando xe ycomo argumentos para do-something-coole seus valores estão sendo definidos na função para ilustrar como você pode usar lambdas para passar argumentos onde nenhum é esperado. A widget.bindfunção espera um eventparâmetro que identifique o evento da GUI nesse widget específico. Eu recomendo a leitura no modelo de programação do Tkinter para maior clareza.
varagrawal
hmm, acho que entendo o modelo Tkinter. Mas ainda não entendi direito - você passa x,ye entende x=event.x. Isso não substitui o valor que você passou? E como a função sabe o que eventé? Não vejo onde você passa isso para a função. Ou é um método? Você também tem sinais de menos em um nome de função?
precisa saber é o seguinte
Amigo @SanjayManohar, você precisa ler sobre Tkinter e Python. Tkinter passa ao objeto de evento a função como uma ação padrão. Quanto ao x, y, isso é apenas um exemplo para fins ilustrativos. Estou tentando mostrar o poder das lambdas, não de Tkinter. :)
varagrawal
1
OK, agora vejo o que você pretendia - deseja que a função receba event? nesse caso, seu lambda não deveria ler lambda event: do_something_cool(event,x,y)?
precisa saber é o seguinte
8

Lambdas estão profundamente ligadas ao estilo de programação funcional em geral. A idéia de que você pode resolver problemas aplicando uma função a alguns dados e mesclando os resultados é o que o Google usa para implementar a maioria de seus algoritmos.

Os programas escritos no estilo de programação funcional são facilmente paralelizados e, portanto, estão se tornando cada vez mais importantes nas modernas máquinas multinúcleo. Então, resumindo, NÃO, você não deve esquecê-los.

Yogi
fonte
7

Primeiros parabéns que conseguiram descobrir lambda. Na minha opinião, é realmente uma construção poderosa para agir. A tendência atual para linguagens de programação funcionais é certamente um indicador de que ela não deve ser evitada nem será redefinida no futuro próximo.

Você só precisa pensar um pouco diferente. Tenho certeza que em breve você vai adorar. Mas tenha cuidado se você lida apenas com python. Como o lambda não é um fechamento real, ele é "quebrado" de alguma forma: pitões lambda são quebrados

Norbert Hartl
fonte
O lambda do Python não está quebrado. Existem duas maneiras de lidar com os habitantes locais em lambdas. Ambos têm vantagens e desvantagens. Eu acho que a abordagem que o Python (e o C #) adotou é provavelmente contra-intuitiva para aqueles mais acostumados a linguagens puramente funcionais, pois com uma linguagem puramente funcional, acho que essa abordagem nem faz sentido.
2027 Brian
É realmente contra-intuitivo. Eu não sou um programador de python, mas no squeak smalltalk é o mesmo e eu passo isso regularmente. Assim, mesmo que eu consideraria "quebrado" :)
Norbert Hartl
Não, isso não tem nada a ver com contra-intuitividade. É apenas que o escopo lexical dos nomes de variáveis ​​é o de uma função; um loop não introduz um escopo lexical. As funções também funcionam da mesma maneira em Javascript. Se você precisa de um espaço para var, você sempre pode fazer (lambda scopedvar: lambda x: scopedvar + x) ()
Antti Haapala
6

Estou apenas começando o Python e corri de cabeça para o Lambda - o que levou um tempo para descobrir.

Observe que isso não é uma condenação de nada. Todo mundo tem um conjunto diferente de coisas que não acontecem facilmente.

O lambda é um daqueles itens de linguagem "interessantes" que na vida real devem ser esquecidos?

Não.

Tenho certeza de que existem alguns casos extremos nos quais isso pode ser necessário, mas, dada a obscuridade,

Não é obscuro. Nas duas últimas equipes em que trabalhei, todo mundo usava esse recurso o tempo todo.

o potencial de ser redefinido em versões futuras (minha suposição com base nas várias definições)

Não vi propostas sérias para redefini-lo no Python, além de corrigir a semântica de fechamento alguns anos atrás.

e a clareza de codificação reduzida - isso deve ser evitado?

Não está menos claro, se você estiver usando certo. Pelo contrário, ter mais construções de linguagem disponíveis aumenta a clareza.

Isso me lembra o transbordamento (buffer overflow) dos tipos C - apontando para a variável superior e a sobrecarga para definir os outros valores de campo ... uma espécie de talento técnico, mas pesadelo do codificador de manutenção.

Lambda é como buffer overflow? Uau. Não consigo imaginar como você está usando o lambda se você acha que é um "pesadelo de manutenção".

Ken
fonte
5
-1 por me fazer (e outros) ler a pergunta toda novamente. Observe que outros conseguiram responder sem fazer isso.
Paweł Polewicz 20/05/09
6

Eu uso lambdas para evitar duplicação de código. Isso tornaria a função facilmente compreensível, por exemplo:

def a_func()
  ...
  if some_conditon:
     ...
     call_some_big_func(arg1, arg2, arg3, arg4...)
  else
     ...
     call_some_big_func(arg1, arg2, arg3, arg4...)

Eu substituo isso por um temp lambda

def a_func()
  ...
  call_big_f = lambda args_that_change: call_some_big_func(arg1, arg2, arg3, args_that_change)
  if some_conditon:
     ...
     call_big_f(argX)
  else
     ...
     call_big_f(argY)
balki
fonte
5

Comecei a ler o livro de David Mertz hoje 'Text Processing in Python'. Embora ele tenha uma descrição bastante concisa dos exemplos de Lambda, os exemplos no primeiro capítulo combinados com a explicação no Apêndice A os fizeram pular da página para mim (finalmente) e, de repente, entendi seu valor. Isso não quer dizer que a explicação dele funcionará para você e eu ainda estou no estágio de descoberta, por isso não tentarei adicionar essas respostas além das seguintes: Eu sou novo no Python Eu sou novo no OOP Lambdas foram uma luta para mim Agora que li Mertz, acho que as compreendo e as vejo tão úteis quanto acho que permitem uma abordagem mais limpa da programação.

Ele reproduz o Zen de Python, cuja linha é simples, é melhor que complexa. Como programador não OOP, lendo código com lambdas (e até a lista de compreensões da semana passada), pensei: isso é simples? . Finalmente, percebi hoje que, na verdade, esses recursos tornam o código muito mais legível e compreensível do que a alternativa - que é invariavelmente um loop de algum tipo. Eu também percebi que, como as demonstrações financeiras, o Python não foi projetado para o usuário iniciante, mas para o usuário que deseja ser educado. Não acredito como essa linguagem é poderosa. Quando me ocorreu (finalmente) o objetivo e o valor das lambdas, eu queria criar cerca de 30 programas e começar a colocar lambdas sempre que apropriado.

PyNEwbie
fonte
5

Um caso útil para usar lambdas é melhorar a legibilidade das compreensões de listas longas . Neste exemplo, loop_dicé uma abreviação de clareza, mas imagine loop_dicser muito longo. Se você usasse apenas um valor simples que inclua, em ivez da versão lambda desse valor, obteria um NameError.

>>> lis = [{"name": "Peter"}, {"name": "Josef"}]

>>> loop_dic = lambda i: {"name": i["name"] + " Wallace" }
>>> new_lis = [loop_dic(i) for i in lis]

>>> new_lis
[{'name': 'Peter Wallace'}, {'name': 'Josef Wallace'}]

Ao invés de

>>> lis = [{"name": "Peter"}, {"name": "Josef"}]

>>> new_lis = [{"name": i["name"] + " Wallace"} for i in lis]

>>> new_lis
[{'name': 'Peter Wallace'}, {'name': 'Josef Wallace'}]
Bentley4
fonte
5

Posso dar um exemplo em que eu realmente precisava de um lambda sério. Estou criando um programa gráfico, em que o uso clica com o botão direito do mouse em um arquivo e atribui a ele uma das três opções. Acontece que no Tkinter (o programa de interface da GUI em que estou escrevendo isso), quando alguém pressiona um botão, ele não pode ser atribuído a um comando que recebe argumentos. Portanto, se eu escolher uma das opções e desejar que o resultado da minha escolha seja:

print 'hi there'

Então não é grande coisa. Mas e se eu precisar da minha escolha para ter um detalhe específico. Por exemplo, se eu escolher a opção A, ela chamará uma função que aceita algum argumento que depende da opção A, B ou C, o TKinter não suportaria isso. Lamda era a única opção para contornar isso, na verdade ...

Glueberg
fonte
2
Bem, presumivelmente você poderia ter feito def foo...e depois passado em foovez de lambda. É apenas mais código e você precisa criar um nome.
Jon Coombs
4

Eu o uso com bastante frequência, principalmente como um objeto nulo ou para ligar parcialmente parâmetros a uma função.

Aqui estão alguns exemplos:

para implementar o padrão de objeto nulo:

{
    DATA_PACKET: self.handle_data_packets
    NET_PACKET: self.handle_hardware_packets
}.get(packet_type, lambda x : None)(payload)

para ligação de parâmetro:

digamos que eu tenho a seguinte API

def dump_hex(file, var)
    # some code
    pass

class X(object):
    #...
    def packet_received(data):
        # some kind of preprocessing
        self.callback(data)
    #...

Então, quando não quiser despejar rapidamente os dados recebidos em um arquivo, faço o seguinte:

dump_file = file('hex_dump.txt','w')
X.callback = lambda (x): dump_hex(dump_file, x)
...
dump_file.close()
Piotr Czapla
fonte
4

eu uso lambda para criar retornos de chamada que incluem parâmetros. É mais limpo escrever um lambda em uma linha do que escrever um método para executar a mesma funcionalidade.

Por exemplo:

import imported.module

def func():
    return lambda: imported.module.method("foo", "bar")

em oposição a:

import imported.module

def func():
    def cb():
        return imported.module.method("foo", "bar")
    return cb
NuclearPeon
fonte
4

Como sou iniciante em python, para obter uma idéia clara do lambda, comparei-o com um loop 'for'; em termos de eficiência. Aqui está o código (python 2.7) -

import time
start = time.time() # Measure the time taken for execution

def first():
    squares = map(lambda x: x**2, range(10))
    # ^ Lambda
    end = time.time()
    elapsed = end - start
    print elapsed + ' seconds'
    return elapsed # gives 0.0 seconds

def second():
    lst = []
    for i in range(10):
        lst.append(i**2)
    # ^ a 'for' loop
    end = time.time()
    elapsed = end - start
    print elapsed + ' seconds'
    return elapsed # gives 0.0019998550415 seconds.

print abs(second() - first()) # Gives 0.0019998550415 seconds!(duh)
Pratik Kulkarni
fonte
6
Você pode estar interessado no timeitmódulo, que normalmente fornece resultados mais precisos do que subtraindo time.time()valores.
Kevin
2
Hmm, você não precisa reiniciar o timer no início do primeiro () e do segundo ()?
Qneill 14/05
2

Lambda é um construtor de procedimentos. Você pode sintetizar programas em tempo de execução, embora o lambda do Python não seja muito poderoso. Observe que poucas pessoas entendem esse tipo de programação.

Nick Dandoulakis
fonte