¿Por qué son útiles las lambdas de Python? [cerrado]

929

Estoy tratando de descubrir Python lambdas. ¿Es lambda uno de esos elementos de lenguaje "interesantes" que en la vida real deberían olvidarse?

Estoy seguro de que hay algunos casos extremos en los que podría ser necesario, pero dada la oscuridad del mismo, el potencial de que se redefina en futuras versiones (mi suposición se basa en las diversas definiciones) y la claridad de codificación reducida, en caso de que sea necesario. ser evitado?

Esto me recuerda el desbordamiento (desbordamiento del búfer) de los tipos C, apuntando a la variable superior y sobrecargando para establecer los otros valores de campo. Se siente como una especie de espectáculo técnico pero pesadilla de codificador de mantenimiento.

meade
fuente
261
+1 Buena pregunta - malas suposiciones (oscuridad de lambda) =) Intenta no juzgar las técnicas de programación. Evalúelos y agréguelos a su conjunto de herramientas mentales. Si no te gustan, no los uses, y prepárate para discutirlos lógicamente sin convertirte en religioso.
Kieveli
41
Haskell Reglas! Las funciones Lambda le brindan expresividad y poder de abstracción.
Jonathan Barbero
11
@JAL Sin mencionar LISP ...
ApproachingDarknessFish
8
@ApproachingDarknessFish "Ah, ese es el paréntesis de tu padre. Un arma más civilizada de una época más civilizada". - Obi Lisp Kenobi
Campos

Respuestas:

1009

¿Estás hablando de funciones lambda ? Me gusta

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

Esas cosas son realmente bastante útiles. Python admite un estilo de programación llamado programación funcional donde puede pasar funciones a otras funciones para hacer cosas. Ejemplo:

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

establece mult3en [3, 6, 9], aquellos elementos de la lista original que son múltiplos de 3. Esto es más corto (y, se podría argumentar, más claro) que

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

Por supuesto, en este caso particular, podría hacer lo mismo que una lista de comprensión:

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

(o incluso como range(3,10,3)), pero hay muchos otros casos de uso más sofisticados en los que no puede utilizar una comprensión de lista y una función lambda puede ser la forma más corta de escribir algo.

  • Devolver una función de otra función

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

    Esto se usa a menudo para crear envoltorios de funciones, como los decoradores de Python.

  • Combinando elementos de una secuencia iterable con 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'
  • Ordenar por una tecla 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]

Yo uso las funciones lambda de forma regular. Me tomó un tiempo acostumbrarme a ellos, pero finalmente llegué a comprender que son una parte muy valiosa del lenguaje.

David Z
fuente
26
Me encantan los ejemplos, muy fáciles de entender. Pero por la parte reducida. Si tengo que implementar esta característica. Lo haría','.join(str(x) for x in [1,2,3,4,5,6,7,8,9])
etlds
3
Por cierto, si ejecuta esto en Python3, debe llamar a la lista de resultados del filtro para ver los valores reales, también debe importar reducir desde functools
Gerard
¿Estamos seguros de la definición de "programación funcional" anterior? Me resultó un poco confuso.
stdout
3
Creo que el punto clave es que las lambdafunciones pueden ser anónimas (como lo son en todos sus ejemplos). Si está asignando una lambdafunción a algo, lo está haciendo mal y debería usarlo defen su lugar
Chris_Rands
1
@zgulser No es una definición, es solo una declaración sobre algo que la programación funcional le permite hacer.
David Z
377

lambdaes solo una forma elegante de decir function. Aparte de su nombre, no hay nada oscuro, intimidante o críptico al respecto. Cuando se lee la siguiente línea, sustituir lambdapor functionen su mente:

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

Simplemente define una función de x. Algunos otros idiomas, como R, lo dicen explícitamente:

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

¿Lo ves? Es una de las cosas más naturales que hacer en la programación.

usuario251650
fuente
36
Esta es una gran descripción para aquellos que provienen de entornos que no son de programación (es decir, ciencias exactas), lo que hace que el significado sea lambda muy simple de entender. ¡Gracias!
Gabriel
10
Raymond Hettinger lamentó el nombre en una de sus charlas y dijo que toda confusión podría haberse evitado nombrándolo 'hacer función' en lugar de 'lambda'. :-)
ankush981
10
reemplazar lambdapor functionen su mente y agregar returnantes de la última expresión
Ciprian Tomoiagă
44
@AaronMcMillin Pruébalo type(lambda x: 3). lambdatanto las expresiones como las defdeclaraciones generan functionobjetos; es solo la sintaxis de una lambdaexpresión la que limita las instancias que puede producir.
chepner
66
@AaronMcMillin Te estás perdiendo mi punto. El hecho de que no pueda definir cada función con una lambdaexpresión no significa que el resultado de una lambdaexpresión no sea una función.
chepner
107

El resumen de dos líneas:

  1. Cierres : muy útiles. Aprendelas, úsalas, ámalas.
  2. Palabra lambdaclave de Python : innecesaria, ocasionalmente útil. Si te encuentras haciendo algo remotamente complejo con él, guárdalo y define una función real.
John Fouhy
fuente
72

Una lambda es parte de un mecanismo de abstracción muy importante que se ocupa de funciones de orden superior. Para obtener una comprensión adecuada de su valor, vea las lecciones de alta calidad de Abelson y Sussman , y lea el libro SICP

Estos son problemas relevantes en el negocio de software moderno, y se están volviendo cada vez más populares.

egaga
fuente
1
Las expresiones lambda también se están volviendo populares en otros lenguajes (como C #). No van a ir a ninguna parte. Leer sobre los cierres sería un ejercicio útil para entender a Lambdas. Los cierres hacen posible una gran cantidad de magia de codificación en marcos como jQuery.
Dan Esparza
3
No confundas lambdasy funciones de primera clase. Python tiene una lambdadeclaración extremadamente limitada , pero funciones completamente de primera clase. La única diferencia que hace es que debe nombrar las funciones que desea transmitir.
Gareth Latty
59

Las lambdas son extremadamente útiles en la programación de la GUI. Por ejemplo, supongamos que está creando un grupo de botones y desea utilizar una única devolución de llamada paramaterizada en lugar de una devolución de llamada única por botón. Lambda te permite lograr eso con facilidad:

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

(Nota: aunque esta pregunta se refiere específicamente lambda, también puede usar functools.partial para obtener el mismo tipo de resultado)

La alternativa es crear una devolución de llamada separada para cada botón que puede conducir a un código duplicado.

Bryan Oakley
fuente
1
Esto es exactamente por qué busqué qué era lambda, pero por qué funciona esto, para mí se ve exactamente igual que simplemente llamar a la función directamente ( stackoverflow.com/questions/3704568/… ). Tal vez sea tarde, funciona, pero ¿por qué funciona?
Rqomey
55
@Rqomey: la diferencia es que en este ejemplo valuese define en un bucle; en el otro ejemplo, el parámetro siempre solo tenía un valor. Cuando agrega algo como arg=value, está adjuntando el valor actual a la devolución de llamada. Sin ella, se vincula una referencia a la variable en la devolución de llamada. La referencia siempre contendrá el valor final de la variable, ya que la devolución de llamada ocurre algún tiempo después de que el ciclo ya haya terminado de ejecutarse.
Bryan Oakley
1
Acabo de hacer que esto funcione ayer, honestamente, no puedo creer lo útil que es ... Puedo crear un menú a partir de uno para el bucle y un archivo csv para la configuración. Cosas realmente útiles.
Rqomey
1
Tenga en cuenta la existencia de lo functools.partial()que le permite hacer esto con menos cruft (y sin lambda).
Gareth Latty
2
partial(my_callback, value)vs lambda arg=value: my_callback(arg): el lambda tiene mucho más rudo (asignación a arg y luego uso) y no está claro cuál es la intención (podría estar haciendo algo sutilmente diferente en el lambda). Las importaciones no son realmente un problema (tienes un montón de todos modos y es una vez por archivo). El código se juzga mejor según lo bien que se lee, y partial()es mucho más fácil de leer que la lambda.
Gareth Latty
58

Dudo que lambda se vaya. Vea la publicación de Guido sobre finalmente dejar de intentar eliminarlo. También vea un resumen del conflicto .

Puede consultar esta publicación para obtener más información sobre el acuerdo detrás de las características funcionales de Python: http://python-history.blogspot.com/2009/04/origins-of-pythons-functional-features.html

Curiosamente, las funciones de mapa, filtro y reducción que originalmente motivaron la introducción de lambda y otras características funcionales han sido reemplazadas en gran medida por las comprensiones de listas y las expresiones generadoras. De hecho, la función de reducción se eliminó de la lista de funciones integradas en Python 3.0. (Sin embargo, no es necesario enviar quejas sobre la eliminación de lambda, mapa o filtro: se están quedando. :-)

Mis propios dos centavos: rara vez vale la pena lambda en lo que respecta a la claridad. Generalmente hay una solución más clara que no incluye lambda.

rhettg
fuente
2
tenga en cuenta que reducir todavía es importante en Python 3.0. Si REALMENTE lo quieres, aún puedes tenerlo.
Paweł Polewicz
Creo que el intento de Guido fue más sobre la sintaxis. Esta persona también piensa que: cackhanded.com/blog/post/2008/01/24/…
leewz
38

En Python, lambdaes solo una forma de definir funciones en línea,

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

y..

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

..son exactamente lo mismo.

No hay nada que pueda hacer con lambda que no pueda hacer con una función regular: en Python las funciones son un objeto como cualquier otra cosa, y lambdas simplemente define una función:

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

Sinceramente, creo que la lambdapalabra clave es redundante en Python: nunca he tenido la necesidad de usarla (o he visto una utilizada donde una función regular, una comprensión de lista o una de las muchas funciones integradas podrían haberse utilizado mejor)

Para un ejemplo completamente al azar, del artículo "¡La lambda de Python está rota!" :

Para ver cómo se rompe lambda, intente generar una lista de funciones fs=[f0,...,f9]donde fi(n)=i+n. Primer intento:

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

Yo diría que, incluso si eso funcionó, es horriblemente y "antipático", la misma funcionalidad podría escribirse de muchas otras maneras, por ejemplo:

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

Sí, no es lo mismo, pero nunca he visto una causa en la que se haya requerido generar un grupo de funciones lambda en una lista. Puede tener sentido en otros idiomas, pero Python no es Haskell (o Lisp, o ...)

Tenga en cuenta que podemos usar lambda y aún así lograr los resultados deseados de esta manera:

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

Editar:

Hay algunos casos en los que lambda es útil, por ejemplo, a menudo es conveniente al conectar señales en aplicaciones PyQt, como esta:

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

Simplemente hacerlo w.textChanged.connect(dothing)llamaría al dothingmétodo con un eventargumento adicional y causaría un error. El uso de lambda significa que podemos descartar el argumento sin tener que definir una función de ajuste.

dbr
fuente
2
su argumento "lambda está roto" está roto, debido a que las reglas de alcance de la variable python funcionan de esa manera, punto. Serás mordido de la misma manera si creaste un cierre dentro del ciclo for.
Antti Haapala
1
lambda es solo la forma en que Python proporciona al usuario una función "anónima", como muchos otros lenguajes tienen (por ejemplo, javascript).
Stefan Gruenwald
1
La lambda y las funciones aque definió no son exactamente las mismas. :) Se diferencian por __name__campo al menos ...
nperson325681
1
Funciona más que una simple función en línea.
kta
Su argumento sobre "podría tener sentido en otro idioma" es extraño. O bien hay cualidades intrínsecas de lambdas, o no lo son.
Titou
31

Encuentro lambda útil para una lista de funciones que hacen lo mismo, pero para diferentes circunstancias.

Como las reglas plurales de 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'

Si tuviera que definir una función para todos esos, se volvería loco al final.
Además, no sería bueno con nombres de funciones como plural_rule_1,plural_rule_2 etc. Y lo necesitarías eval()cuando dependas de una identificación de función variable.

Tor Valamo
fuente
1
Esto se parece a los breves encuentros que he tenido hasta ahora en F # con coincidencia de patrones y opciones. ¿Tiene más información sobre cómo usar esta sintaxis?
Ken
26

Casi cualquier cosa que puedas hacer con lambda usted puede hacerlo mejor con funciones con nombre o con expresiones de lista y generador.

En consecuencia, en su mayor parte, solo debe uno de esos en prácticamente cualquier situación (excepto tal vez para el código de borrador escrito en el intérprete interactivo).

Aaron Maenpaa
fuente
3
"en su mayor parte, debería ser uno de esos en prácticamente cualquier situación" Período. Escribir lambda en el intérprete ni siquiera es tan útil.
S.Lott
11
@Javier Estoy de acuerdo contigo si estás hablando del concepto "lambda"; sin embargo, si estamos hablando de "lambda", la palabra clave de Python, entonces: 1) las funciones con nombre son más rápidas y pueden hacer más (declaraciones + expresiones) en casi cualquier lugar donde usaría lambdas (mapa + filtro), puede simplemente generar expresiones o enumerar comprensiones que son más efectivos y concisos. No digo que las funciones de primera clase no sean geniales, solo que la palabra clave "lambda" en python no es tan buena como usar una función con nombre, eso es todo.
Aaron Maenpaa
3
lambda ha sido indispensable para mí para su uso con las funciones que toman argumentos de devolución de llamada como la llave = argumento para ordenar () y ordenados ()
Rick Copeland
19
@Rick No lo dudo, pero la realidad es que si ves "lambda" y piensas "zohmygod lambda" y comienzas a escribir código de esquema en python, estarás decepcionado por las limitaciones de la expresión lambda de python. Por otro lado, si comienzas a pensar para ti mismo "¿Funcionará una comprensión de la lista? No. ¿Lo que necesito me beneficiará de ser una función nombrada? No. Bien, bien: ordenado (xs, key = lambda x: x.name, x.height) ", probablemente terminarás usando lambda la cantidad correcta de veces.
Aaron Maenpaa
44
+1: No puedo enfatizar eso lo suficiente cuando uno usa una lambda, usa una función sin nombre . Y los nombres tienen un valioso valor intelectual añadido.
Stephane Rolland
19

He estado usando Python durante algunos años y nunca me he encontrado con un caso en el que necesito lambda. Realmente, como dice el tutorial , es solo para el azúcar sintáctico.

Matt Schmidt
fuente
8
Son muy útiles al desarrollar una GUI usando python. A menudo, los widgets necesitan una referencia a una función. Si necesita un widget para llamar a una función y pasar argumentos, lambda es una forma muy conveniente de hacerlo.
Bryan Oakley
1
¿Cuál es la ventaja sobre pasar múltiples argumentos a la función? func_name (a, b): devuelve a + b en lugar de usar lambda
dter
2
no es necesario, pero ayuda a escribir código más corto y más legible en muchos casos, especialmente. en lenguajes detallados como Java o C ++
phuclv
17

No puedo hablar de la implementación particular de lambda en Python, pero en general las funciones lambda son realmente útiles. Son una técnica central (quizás incluso LA técnica) de programación funcional, y también son muy útiles en programas orientados a objetos. Para ciertos tipos de problemas, son la mejor solución, por lo que no debe olvidarse.

Le sugiero que lea sobre los cierres y la función de mapa (que enlaza con documentos de Python, pero existe en casi todos los idiomas que admiten construcciones funcionales) para ver por qué es útil.

rmeador
fuente
3
Eso se puede hacer sin lambdas. Es solo una gran molestia.
Brian
17

La función Lambda es una forma no burocrática de crear una función.

Eso es. Por ejemplo, supongamos que tiene su función principal y necesita ajustar los valores al cuadrado. Veamos la forma tradicional y la forma lambda de hacer esto:

Forma tradicional:

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

def square(x):
    return x**2

La forma lambda:

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

¿Ver la diferencia?

Las funciones de Lambda van muy bien con listas, como listas de comprensión o mapas. De hecho, la comprensión de la lista es una forma "pitónica" de expresarse usando lambda. Ex:

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

Veamos qué significa cada elemento de la sintaxis:

[]: "Dame una lista"

x ** 2: "usando esta función recién nacida"

para x en a: "en cada elemento en a"

Eso es conveniente, ¿eh? Creando funciones como esta. Reescribámoslo usando lambda:

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

Ahora usemos map, que es lo mismo, pero más neutral en cuanto al idioma. Mapas toma 2 argumentos:

(i) una función

(ii) un iterable

Y le da una lista donde cada elemento es la función aplicada a cada elemento del iterable.

Entonces, usando el mapa tendríamos:

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

Si domina las lambdas y el mapeo, tendrá un gran poder para manipular datos y de manera concisa. Las funciones de Lambda no son oscuras ni eliminan la claridad del código. No confundas algo duro con algo nuevo. Una vez que comience a usarlos, lo encontrará muy claro.

Lucas Ribeiro
fuente
13

Una de las cosas buenas de lambda mi opinión, esto es que es una forma de diferir una evaluación para formularios simples hasta que se necesite el valor. Dejame explicar.

Se implementan muchas rutinas de biblioteca para que permitan que ciertos parámetros sean invocables (de los cuales lambda es uno). La idea es que el valor real se computará solo en el momento en que se va a usar (en lugar de cuando se lo llame). Un ejemplo (artificial) podría ayudar a ilustrar el punto. Supongamos que tiene una rutina que iba a registrar una marca de tiempo dada. Desea que la rutina use la hora actual menos 30 minutos. Lo llamarías así

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

Ahora suponga que la función real se llamará solo cuando ocurra un determinado evento y desee que la marca de tiempo se calcule solo en ese momento. Puedes hacer esto así

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

Suponiendo que la log_timestamplata pueda manejar llamadas como esta, evaluará esto cuando lo necesite y obtendrá la marca de tiempo en ese momento.

Por supuesto, hay formas alternativas de hacerlo (usando el operatormódulo, por ejemplo), pero espero haber transmitido el punto.

Actualización : Aquí hay un ejemplo un poco más concreto del mundo real.

Actualización 2 : creo que este es un ejemplo de lo que se llama un thunk .

Noufal Ibrahim
fuente
11

Como se indicó anteriormente, el operador lambda en Python define una función anónima, y ​​en Python las funciones son cierres. Es importante no confundir el concepto de cierres con el operador lambda, que es simplemente metadona sintáctica para ellos.

Cuando comencé en Python hace unos años, usaba muchas lambdas, pensando que eran geniales, junto con las listas de comprensión. Sin embargo, escribí y tengo que mantener un gran sitio web escrito en Python, con el orden de varios miles de puntos de función. Aprendí por experiencia que las lambdas pueden estar bien para hacer prototipos de cosas, pero no ofrecen nada sobre las funciones en línea (cierres con nombre), excepto para guardar algunas claves, o a veces no.

Básicamente esto se reduce a varios puntos:

  • Es más fácil leer el software que está escrito explícitamente usando nombres significativos. Los cierres anónimos por definición no pueden tener un nombre significativo, ya que no tienen nombre. Esta brevedad parece, por alguna razón, infectar también los parámetros lambda, por lo tanto, a menudo vemos ejemplos como lambda x: x + 1
  • es más fácil reutilizar cierres con nombre, ya que se puede hacer referencia a ellos por nombre más de una vez, cuando hay un nombre para referirse a ellos.
  • es más fácil depurar el código que usa cierres con nombre en lugar de lambdas, porque el nombre aparecerá en las trazas y alrededor del error.

Esa es razón suficiente para redondearlos y convertirlos en cierres con nombre. Sin embargo, guardo otros dos rencores contra los cierres anónimos.

El primer rencor es simplemente que son solo otra palabra clave innecesaria que satura el idioma.

El segundo rencor es más profundo y en el nivel de paradigma, es decir, no me gusta que promuevan un estilo de programación funcional, porque ese estilo es menos flexible que el paso de mensajes, orientado a objetos o estilos de procedimiento, porque el cálculo lambda no es Turing- completo (por suerte en Python, aún podemos romper esa restricción incluso dentro de una lambda). Las razones por las que siento que las lambdas promueven este estilo son:

  • Hay un retorno implícito, es decir, parece que 'deberían' ser funciones.

  • Son un mecanismo alternativo para ocultar el estado de otro mecanismo más explícito, más legible, más reutilizable y más general: los métodos.

Intento escribir Python libre de lambda y eliminar lambdas a la vista. Creo que Python sería un lenguaje un poco mejor sin lambdas, pero esa es solo mi opinión.

Mike A
fuente
1
"... en Python las funciones son cierres". Eso no está del todo bien, según tengo entendido. Los cierres son funciones, pero las funciones no siempre son cierres. Función-> lambda x, y: x + y. Cierre-> lambda x: lambda y: x + y
0atman
66
"porque el cálculo lambda no está completo de Turing" es simplemente incorrecto, el cálculo lambda sin tipo ES Turing completo, esa es la razón por la cual es tan significativo. Puede obtener recursividad utilizando el combinador Y,Y = lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args)))
Antti Haapala
Además, si uno va a Wikipedia para leer sobre la integridad de Turing, dice "Un ejemplo clásico es el cálculo lambda".
Antti Haapala
En serio, no está completo, esta respuesta necesita una edición o retracción seria.
Tony Suffolk 66
@ MarcinŁoś Elegido porque se adhiere a KISS. A modo de comparación, el libro de K&R menciona que si bien el uso de la asignación como parte o una expresión más grande es más compacto, a menudo es menos legible. La tendencia de usar patrones de programación funcionales es trivial y cliché. Es suficiente indicar cómo se pueden usar, pero es demasiado entusiasta afirmar que son fundamentales para convertirse en un desarrollador competente; completamente subjetivo Este argumento es análogo a los desarrolladores de C ++ que sostienen que los lenguajes sin clases son primitivos, inferiores e inadecuados. "Turing-completeness", los argumentos son pedantes.
typedeaf
11

Las lambdas son en realidad construcciones muy poderosas que surgen de ideas en programación funcional, y es algo que de ninguna manera será fácilmente revisado, redefinido o eliminado en el futuro cercano de Python. Le ayudan a escribir código que es más poderoso ya que le permite pasar funciones como parámetros, de ahí la idea de funciones como ciudadanos de primera clase.

Las lambdas tienden a ser confusas, pero una vez que se obtiene una comprensión sólida, puede escribir código elegante y limpio como este:

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

La línea de código anterior devuelve una lista de los cuadrados de los números en la lista. Por supuesto, también puedes hacerlo como:

def square(x):
    return x*x

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

Es obvio que el código anterior es más corto, y esto es especialmente cierto si tiene la intención de utilizar la función de mapa (o cualquier función similar que tome una función como parámetro) en un solo lugar. Esto también hace que el código sea más intuitivo y elegante.

Además, como @David Zaslavsky mencionó en su respuesta, las comprensiones de listas no siempre son el camino a seguir, especialmente si su lista tiene que obtener valores de alguna forma matemática oscura.

Desde un punto de vista más práctico, una de las mayores ventajas de lambdas para mí recientemente ha sido la GUI y la programación basada en eventos. Si observa las devoluciones de llamada en Tkinter, todo lo que toman como argumentos es el evento que los activó. P.ej

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

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

¿Y si tuvieras que pasar algunos argumentos? Algo tan simple como pasar 2 argumentos para almacenar las coordenadas de un clic del mouse. Puedes hacerlo fácilmente así:

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

Ahora puede argumentar que esto se puede hacer usando variables globales, pero ¿realmente quiere golpearse la cabeza preocupándose por la gestión de la memoria y las fugas, especialmente si la variable global solo se usará en un lugar en particular? Eso sería un mal estilo de programación.

En resumen, las lambdas son increíbles y nunca deben subestimarse. Sin embargo, las lambdas de Python no son lo mismo que las lambdas de LISP (que son más poderosas), pero realmente puedes hacer muchas cosas mágicas con ellas.

varagrawal
fuente
Gracias. No entendí completamente tu último ejemplo. ¿Cómo es que x e y se definen en ambos mainy do_something_cool? ¿Qué pasa con xy yen la función? ¿Los valores pasados ​​parecen sobrescribirse inmediatamente? ¿Cómo sabe la función event? ¿Podría agregar algunos comentarios / explicaciones? Gracias
Sanjay Manohar
@SanjayManohar que paso xy ycomo argumentos do-something-cooly sus valores se establecen en la función para ilustrar cómo puede usar lambdas para pasar argumentos donde no se espera ninguno. La widget.bindfunción espera un eventparámetro que identifique el evento GUI en ese widget en particular. Recomiendo leer en el modelo de programación de Tkinter para mayor claridad.
varagrawal
hmm creo que entiendo el modelo Tkinter. Pero aún no lo entiendo del todo: pasa y x,yluego lo hace x=event.x. ¿Eso no sobrescribe el valor que pasó? ¿Y cómo sabe la función qué eventes? No veo dónde pasas eso a la función. ¿O es un método? ¿También se le permiten signos menos en el nombre de una función?
Sanjay Manohar
@SanjayManohar amigo, necesitas leer sobre Tkinter y Python. Tkinter pasa al objeto de evento la función como una acción predeterminada. En cuanto al x, y, eso es solo un ejemplo con fines ilustrativos. Estoy tratando de mostrar el poder de las lambdas, no de Tkinter. :)
varagrawal
1
Bien, ahora veo lo que pretendías: ¿quieres que reciba la función event? en ese caso, ¿no debería leer tu lambda lambda event: do_something_cool(event,x,y)?
Sanjay Manohar
8

Las lambdas están profundamente vinculadas al estilo de programación funcional en general. La idea de que puede resolver problemas aplicando una función a algunos datos y fusionando los resultados es lo que google utiliza para implementar la mayoría de sus algoritmos.

Los programas escritos en un estilo de programación funcional, se paralelizan fácilmente y, por lo tanto, se vuelven cada vez más importantes con las máquinas modernas de múltiples núcleos. En resumen, NO, no debes olvidarlos.

Yogui
fuente
7

Primeras felicitaciones que lograron descubrir lambda. En mi opinión, esta es una construcción realmente poderosa para actuar. La tendencia en estos días hacia los lenguajes de programación funcional es seguramente un indicador de que no debe evitarse ni redefinirse en un futuro próximo.

Solo tienes que pensar un poco diferente. Estoy seguro de que pronto te encantará. Pero ten cuidado si solo tratas con python. Debido a que el lambda no es un cierre real, está "roto" de alguna manera: pitones lambda está roto

Norbert Hartl
fuente
La lambda de Python no está rota. Hay dos formas de manejar a los locales en lambdas. Ambos tienen ventajas y desventajas. Creo que el enfoque que tomó Python (y C #) probablemente sea contradictorio para aquellos más acostumbrados a los lenguajes puramente funcionales, ya que con un lenguaje puramente funcional no creo que ese enfoque tenga sentido.
Brian
De hecho, es contraintuitivo. No soy un programador de Python, pero en Squeak Smalltalk es lo mismo y me encuentro con esto regularmente. Así que incluso yo lo consideraría "roto" :)
Norbert Hartl
No, esto no tiene nada que ver con la contraintuitividad. Es solo que el alcance léxico de los nombres de variables es el de una función; un bucle no introduce un alcance léxico. Las funciones también funcionan de la misma manera en Javascript. Si necesita un alcance para var, siempre puede hacerlo (lambda scopedvar: lambda x: scopedvar + x) ()
Antti Haapala
6

Estoy empezando Python y me topé con Lambda, lo que me llevó un tiempo descubrir.

Tenga en cuenta que esto no es una condena de nada. Todo el mundo tiene un conjunto diferente de cosas que no son fáciles.

¿Es lambda uno de esos elementos de lenguaje 'interesantes' que en la vida real deberían olvidarse?

No.

Estoy seguro de que hay algunos casos extremos en los que podría ser necesario, pero dada la oscuridad,

No es oscuro En los últimos 2 equipos en los que he trabajado, todos usaron esta función todo el tiempo.

El potencial de su redefinición en futuras versiones (mi suposición basada en las diversas definiciones de la misma)

No he visto propuestas serias para redefinirlo en Python, más allá de arreglar la semántica de cierre hace unos años.

y la claridad de codificación reducida: ¿se debe evitar?

No está menos claro, si lo estás usando bien. Por el contrario, tener más construcciones de lenguaje disponibles aumenta la claridad.

Esto me recuerda al desbordamiento (desbordamiento del búfer) de los tipos C, apuntando a la variable superior y sobrecargando para establecer los otros valores de campo ... una especie de espectáculo técnico pero pesadilla del codificador de mantenimiento ...

Lambda es como desbordamiento de búfer? Guau. No puedo imaginar cómo estás usando lambda si crees que es una "pesadilla de mantenimiento".

Conocer
fuente
55
-1 por hacer que yo (y otros) leamos toda la pregunta nuevamente. Tenga en cuenta que otros lograron responder sin hacerlo.
Paweł Polewicz
6

Yo uso lambdas para evitar la duplicación de código. Haría la función fácilmente comprensible, por ejemplo:

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

Reemplazo eso con una temperatura 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
fuente
5

Hoy comencé a leer el libro de David Mertz "Procesamiento de texto en Python". Si bien tiene una descripción bastante concisa de Lambda, los ejemplos en el primer capítulo combinados con la explicación en el Apéndice A los hicieron saltar de la página para mí (finalmente) y de repente entendí su valor. Eso no quiere decir que su explicación funcione para usted y todavía estoy en la etapa de descubrimiento, así que no intentaré agregar a estas respuestas más que lo siguiente: Soy nuevo en Python Soy nuevo en OOP Lambdas fue una lucha para mí Ahora que leí Mertz, creo que los entiendo y los veo tan útiles como creo que permiten un enfoque más limpio de la programación.

Reproduce el Zen de Python, una línea de la cual es simple es mejor que compleja. Como un programador que no es OOP leyendo códigos con lambdas (y hasta la semana pasada comprendo la lista), pensé: ¿ Esto es simple? . Finalmente me di cuenta hoy de que en realidad estas características hacen que el código sea mucho más legible y comprensible que la alternativa, que es invariablemente un bucle de algún tipo. También me di cuenta de que, como los estados financieros, Python no fue diseñado para el usuario novato, sino que está diseñado para el usuario que quiere educarse. No puedo creer lo poderoso que es este lenguaje. Cuando caí en la cuenta (finalmente) el propósito y el valor de las lambdas, quería desarrollar unos 30 programas y comenzar a poner lambdas cuando sea apropiado.

PyNEwbie
fuente
5

Un caso útil para usar lambdas es mejorar la legibilidad de las comprensiones de listas largas . En este ejemplo loop_dices corto para mayor claridad, pero imagina que loop_dices muy largo. Si solo usara un valor simple que incluyera en ilugar de la versión lambda de ese valor, obtendría un 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'}]

En vez 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
fuente
5

Puedo darte un ejemplo donde realmente necesitaba lambda serio. Estoy haciendo un programa gráfico, donde el uso hace clic derecho en un archivo y le asigna una de las tres opciones. Resulta que en Tkinter (el programa de interfaz GUI en el que estoy escribiendo esto), cuando alguien presiona un botón, no se puede asignar a un comando que toma argumentos. Entonces, si elegí una de las opciones y quería que el resultado de mi elección fuera:

print 'hi there'

Entonces no es gran cosa. Pero, ¿y si necesito mi elección para tener un detalle particular? Por ejemplo, si elijo la opción A, llama a una función que incluye algún argumento que depende de la opción A, B o C, TKinter no podría admitir esto. Lamda era la única opción para evitar esto en realidad ...

Glueberg
fuente
2
Bueno, presumiblemente podría haberlo hecho def foo...y luego pasar en foolugar de hacerlo lambda. Es solo más código y tienes que encontrar un nombre.
Jon Coombs
4

Lo uso con bastante frecuencia, principalmente como un objeto nulo o para vincular parcialmente parámetros a una función.

Aquí hay ejemplos:

para implementar un patrón de objeto nulo:

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

para el enlace de parámetros:

Digamos que tengo la siguiente API

def dump_hex(file, var)
    # some code
    pass

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

Luego, cuando quiero volcar rápidamente los datos recibidos en un archivo, hago eso:

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

yo suelo lambda para crear devoluciones de llamada que incluyen parámetros. Es más limpio escribir un lambda en una línea que escribir un método para realizar la misma funcionalidad.

Por ejemplo:

import imported.module

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

Opuesto a:

import imported.module

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

Soy un principiante en python, así que para obtener una idea clara de lambda lo comparé con un bucle 'for'; en términos de eficiencia. Aquí está el 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
fuente
66
Puede interesarle el timeitmódulo, que generalmente brinda resultados más precisos que restar time.time()valores.
Kevin
2
Hmm, ¿no necesitas reiniciar tu temporizador al comienzo de first () y second ()?
qneill
2

Lambda es un constructor de procedimientos. Puede sintetizar programas en tiempo de ejecución, aunque la lambda de Python no es muy potente. Tenga en cuenta que pocas personas entienden ese tipo de programación.

Nick Dandoulakis
fuente