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

Estoy tratando de averiguar lambda de Python. ¿Es la lambda uno de esos ítems del lenguaje “interesante” que en la vida real deberían olvidarse?

Estoy seguro de que hay algunos casos de vanguardia en los que podría ser necesario, pero dada la oscuridad de la misma, la posibilidad de que se redefina en futuras versiones (mi suposición basada en las distintas definiciones de la misma) y la claridad de encoding reducida, en caso de que ser evitado?

Esto me recuerda al desbordamiento (desbordamiento del búfer) de los tipos C: apuntando a la variable superior y la sobrecarga para establecer los otros valores de campo. Se siente como una especie de showmanship techie pero pesadilla de codificador de mantenimiento.

¿Estás hablando de funciones lambda ? Me gusta

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

Esas cosas son en realidad bastante útiles. Python admite un estilo de progtwigción llamado progtwigción funcional en el que 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 mult3 a [3, 6, 9] , aquellos elementos de la lista original que son múltiplos de 3. Esto es más corto (y, uno 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 se puede usar una lista de comprensión y una función lambda puede ser la forma más corta de escribir algo.

  • Devolviendo una función desde 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 clave 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 entender que son una parte muy valiosa del idioma.

lambda es sólo una forma elegante de decir la function . Aparte de su nombre, no hay nada oscuro, intimidante o críptico al respecto. Cuando lea la siguiente línea, reemplace lambda por function en 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 para hacer en la progtwigción.

El resumen de dos líneas:

  1. Cierres : Muy útiles. Apréndelos, úsalos, ámalos.
  2. lambda clave lambda de Python: innecesaria, ocasionalmente útil. Si se encuentra haciendo algo remotamente complejo con él, guárdelo y defina una función real.

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

Estos son temas relevantes en el negocio de software moderno, y cada vez son más populares.

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

Puede consultar esta publicación para obtener más de un historial 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, el mapa, el filtro y las funciones de reducción que originalmente motivaron la introducción de lambda y otras características funcionales han sido, en gran medida, reemplazados por la comprensión de listas y las expresiones generadoras. De hecho, la función de reducción se eliminó de la lista de funciones incorporadas en Python 3.0. (Sin embargo, no es necesario enviar quejas sobre la eliminación de lambda, el mapa o el filtro: se están quedando. 🙂

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

Las lambdas son extremadamente útiles en la progtwigción de GUI. Por ejemplo, supongamos que está creando un grupo de botones y desea utilizar una única callback patwigterizada en lugar de una callback única por botón. Lambda te permite lograrlo 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 es específicamente sobre lambda , también puede usar functools.partial para obtener el mismo tipo de resultado)

La alternativa es crear una callback por separado para cada botón, lo que puede dar lugar a un código duplicado.

En Python, lambda es 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) 

..es exactamente igual.

No hay nada que pueda hacer con lambda que no pueda hacer con una función normal; 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)  

Sinceramente, creo que la palabra clave lambda es redundante en Python: nunca he tenido la necesidad de usarlas (o he visto una que se usa cuando una función normal, una lista de comprensión o una de las muchas funciones integradas podrían haberse utilizado mejor en su lugar)

Para un ejemplo completamente aleatorio, 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 bash:

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

Yo diría que, incluso si eso funcionara, es horrible y “no hippónico”, la misma funcionalidad podría escribirse de muchas otras formas, 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. Podría 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 donde lambda es útil, por ejemplo, a menudo es conveniente cuando se conectan señales en aplicaciones PyQt, como esto:

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

Solo hacer w.textChanged.connect(dothing) llamaría al método dothing con un argumento de event adicional y causaría un error. El uso de la lambda significa que podemos eliminar ordenadamente el argumento sin tener que definir una función de ajuste.

Encuentro que lambda es útil para una lista de funciones que hacen lo mismo, pero para diferentes circunstancias. Como las reglas del plural 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 tuvieras que definir una función para todos aquellos a los que te volverías loco al final de la misma. Además, no estaría bien con nombres de funciones como plural_rule_1 , plural_rule_2 , etc. Y necesitarías plural_rule_1 plural_rule_2 de una función variable id.

Casi cualquier cosa que pueda hacer con lambda puede hacerlo mejor con funciones nombradas o con expresiones de lista y generador.

En consecuencia, en su mayor parte, solo debería ser uno de esos en cualquier situación (excepto tal vez para el código de escritura escrito en el intérprete interactivo).

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

No puedo hablar de la implementación particular de python de lambda, pero en general las funciones de lambda son realmente útiles. Son una técnica básica (tal vez incluso LA TÉCNICA) de la progtwigción funcional, y también son muy útiles en progtwigs orientados a objetos. Para ciertos tipos de problemas, son la mejor solución, ¡por lo que ciertamente 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.

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 cuadrar los valores. 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 Lambda van muy bien con listas, como listas de comprensión o mapa. De hecho, la comprensión de lista es una forma “pythonic” de expressse 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 syntax:

[]: “Dame una lista”

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

para x en a: “en cada elemento en a”

Eso es conveniente uh? Creando funciones como esta. Vamos a reescribirlo usando lambda:

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

Ahora usemos el mapa, que es lo mismo, pero más neutral en cuanto al idioma. Mapas lleva 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 de lo iterable.

Entonces, usando el mapa tendríamos:

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

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

Una de las cosas agradables sobre lambda que, en mi opinión, es subestimada es que es una forma de diferir una evaluación de formas simples hasta que se necesita el valor. Dejame explicar.

Muchas rutinas de la biblioteca se implementan de modo que permiten que ciertos parámetros sean callables (de los cuales lambda es uno). La idea es que el valor real se calculará solo en el momento en que se va a utilizar (y no cuando se llama). Un ejemplo (creado) podría ayudar a ilustrar el punto. Supongamos que tiene una rutina que iba a registrar una marca de tiempo determinada. Desea que la rutina use la hora actual menos 30 minutos. Usted lo llamaría así

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

Ahora suponga que la función real se llamará solo cuando ocurra cierto evento y desea 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)) 

Asumiendo que log_timestamp puede manejar log_timestamp esta manera, evaluará esto cuando lo necesite y obtendrá la marca de tiempo en ese momento.

Por supuesto, hay formas alternativas de hacerlo (utilizando el módulo del operator , por ejemplo), pero espero haber transmitido el punto.

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

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

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 una metadona sintáctica para ellos.

Cuando empecé en Python hace unos años, usé mucho las 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 un orden de varios miles de puntos de función. Aprendí por experiencia que las lambdas podrían estar bien para hacer prototipos, pero no ofrecen nada sobre las funciones en línea (cierres con nombre), excepto para guardar algunas claves, o algunas veces no.

Básicamente esto se reduce a varios puntos:

  • es más fácil leer software que se escribe 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, también infectar los parámetros lambda, por lo que a menudo vemos ejemplos como lambda x: x + 1
  • es más fácil reutilizar los cierres con nombre, ya que se puede hacer referencia a ellos más de una vez, cuando hay un nombre para referirse a ellos.
  • es más fácil depurar el código que utiliza cierres con nombre en lugar de lambdas, porque el nombre aparecerá en las trazas y en torno al error.

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

El primer rencor es simplemente que son solo otra palabra clave innecesaria que abarrota el lenguaje.

El segundo rencor es más profundo y en el nivel de paradigma, es decir, no me gusta que promuevan un estilo de progtwigción funcional, ya que ese estilo es menos flexible que los estilos de paso de mensajes, orientados a objetos o procedimientos, porque el cálculo lambda no es Turing completa (por suerte en Python, aún podemos romper esa restricción incluso dentro de un 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 de ocultación del estado a otro mecanismo más explícito, más legible, más reutilizable y más general: los métodos.

Me esfuerzo mucho por escribir Python sin lambda y eliminar las lambdas a la vista. Creo que Python sería un lenguaje un poco mejor sin lambdas, pero esa es solo mi opinión.

Las Lambdas son en realidad construcciones muy poderosas que surgen de ideas en la progtwigció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, por lo tanto, 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 limpio y elegante 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 pretende 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 lo mencionó @David Zaslavsky en su respuesta, la comprensión de la lista no siempre es el camino a seguir, especialmente si su lista tiene que obtener valores de alguna manera 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 progtwigción dirigida por eventos. Si echa un vistazo a las devoluciones de llamada en Tkinter, todos los que toman como argumentos son el evento que los desencadenó. P.ej

 def define_bindings(widget): widget.bind("", do-something-cool) def do-something-cool(event): #Your code to execute on the event trigger 

¿Y ahora si tuvieras algunos argumentos para aprobar? 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("", 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 simplemente un mal estilo de progtwigción.

En resumen, las lambdas son impresionantes y nunca deben ser subestimadas. Las lambdas de Python no son lo mismo que las de LISP (que son más poderosas), pero realmente puedes hacer muchas cosas mágicas con ellas.

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

Los progtwigs escritos en estilo de progtwigción funcional, son fácilmente paralelizados y, por lo tanto, son cada vez más importantes con las modernas máquinas de múltiples núcleos. Así que en definitiva, NO, no debes olvidarlos.

Primeros felicidades que lograron descifrar lambda. En mi opinión, esta es una construcción realmente poderosa para actuar. La tendencia en estos días hacia los lenguajes de progtwigción funcionales es seguramente un indicador de que no debe evitarse ni se redefinirá 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 la lambda no es un cierre real, está “roto” de alguna manera: la pitda lambda está rota

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 un 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) 

Acabo de empezar a Python y corrí con la cabeza hacia Lambda, lo que me llevó un tiempo descifrarlo.

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

¿Es la lambda uno de esos ítems del 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 de la misma,

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

la posibilidad de que se redefina en futuras versiones (mi suposición se basa en las distintas 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 encoding reducida, ¿debería evitarse?

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: apuntar a la variable superior y sobrecargar para establecer los otros valores de campo … una especie de maestría tecnológica pero una pesadilla de mantenimiento del progtwigdor

Lambda es como desbordamiento de búfer? Guau. No puedo imaginarme cómo usas lambda si crees que es una “pesadilla de mantenimiento”.

Comencé a leer el libro de David Mertz hoy ‘Procesamiento de texto en Python’. While he has a fairly terse description of Lambda’s the examples in the first chapter combined with the explanation in Appendix A made them jump off the page for me (finally) and all of a sudden I understood their value. That is not to say his explanation will work for you and I am still at the discovery stage so I will not attempt to add to these responses other than the following: I am new to Python I am new to OOP Lambdas were a struggle for me Now that I read Mertz, I think I get them and I see them as very useful as I think they allow a cleaner approach to programming.

He reproduces the Zen of Python, one line of which is Simple is better than complex. As a non-OOP programmer reading code with lambdas (and until last week list comprehensions) I have thought- This is simple? . I finally realized today that actually these features make the code much more readable, and understandable than the alternative-which is invariably a loop of some sort. I also realized that like financial statements-Python was not designed for the novice user, rather it is designed for the user that wants to get educated. I can’t believe how powerful this language is. When it dawned on me (finally) the purpose and value of lambdas I wanted to rip up about 30 programs and start over putting in lambdas where appropriate.

A useful case for using lambdas is to improve the readability of long list comprehensions . In this example loop_dic is short for clarity but imagine loop_dic being very long. If you would just use a plain value that includes i instead of the lambda version of that value you would get a 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 lugar de

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

I’m a python beginner, so to getter a clear idea of lambda I compared it with a ‘for’ loop; in terms of efficiency. Here’s the code (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) 

I can give you an example where I actually needed lambda serious. I’m making a graphical program, where the use right clicks on a file and assigns it one of three options. It turns out that in Tkinter (the GUI interfacing program I’m writing this in), when someone presses a button, it can’t be assigned to a command that takes in arguments. So if I chose one of the options and wanted the result of my choice to be:

 print 'hi there' 

Then no big deal. But what if I need my choice to have a particular detail. For example, if I choose choice A, it calls a function that takes in some argument that is dependent on the choice A, B or C, TKinter could not support this. Lamda was the only option to get around this actually…

I use it quite often, mainly as a null object or to partially bind parameters to a function.

Here are examples:

to implement null object pattern:

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

for parameter binding:

let say that I have the following API

 def dump_hex(file, var) # some code pass class X(object): #... def packet_received(data): # some kind of preprocessing self.callback(data) #... 

Then, when I wan’t to quickly dump the recieved data to a file I do that:

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

I use lambda to create callbacks that include parameters. It’s cleaner writing a lambda in one line than to write a method to perform the same functionality.

Por ejemplo:

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

as opposed to:

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

Lambda is a procedure constructor. You can synthesize programs at run-time, although Python’s lambda is not very powerful. Note that few people understand that kind of programming.