¿Por qué usar las funciones lambda?

Puedo encontrar muchas cosas que me muestran qué es una función lambda, cómo funciona la syntax y qué no. Pero aparte del “factor de frialdad” (¡puedo hacer una función en medio de una llamada a otra función, limpio!) No he visto algo que sea demasiado convincente para decir por qué realmente necesito / quiero usarlos.

Parece ser más una elección estilística o estructural en la mayoría de los ejemplos que he visto. Y un poco rompe la “única forma correcta de hacer algo” en la regla de python. ¿Cómo hace que mis progtwigs sean más correctos, más confiables, más rápidos o más fáciles de entender? (La mayoría de los estándares de encoding que he visto tienden a decirle que evite las declaraciones demasiado complejas en una sola línea. Si facilita la lectura, divídalo).

Aquí hay un buen ejemplo:

 def key(x): return x[1] a = [(1, 2), (3, 1), (5, 10), (11, -3)] a.sort(key=key) 

versus

 a = [(1, 2), (3, 1), (5, 10), (11, -3)] a.sort(key=lambda x: x[1]) 

Desde otro ángulo: las expresiones Lambda también se conocen como “funciones anónimas”, y son muy útiles en ciertos paradigmas de progtwigción, en particular la progtwigción funcional, en la que el cálculo lambda fue la inspiración.

http://en.wikipedia.org/wiki/Lambda_calculus

La syntax es más concisa en ciertas situaciones, principalmente cuando se trata de map et al.

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

me parece mejor que

 def double(x): return x * 2 map(double, [1,2,3,4]) 

Creo que la lambda es una mejor opción en esta situación porque la def double parece casi desconectada del map que la está utilizando. Además, supongo que tiene el beneficio adicional de que la función se desecha cuando terminas.

Hay un inconveniente de la lambda que limita su utilidad en Python, en mi opinión: las lambdas solo pueden tener una expresión (es decir, no puedes tener varias líneas). Simplemente no puede funcionar en un lenguaje que obliga a los espacios en blanco.

Además, cada vez que uso lambda me siento increíble.

Las funciones Lambda son más útiles en cosas como las funciones de callback o lugares en los que necesita una función desechable. El ejemplo de JAB es perfecto: estaría mejor acompañado por la clave de argumento de palabra key , pero aún así proporciona información útil.

Cuando

 def key(x): return x[1] 

aparece a 300 líneas de distancia de

 [(1,2), (3,1), (5,10), (11,-3)].sort(key) 

¿Qué hace la clave? Realmente no hay ninguna indicación. Es posible que tenga algún tipo de conjetura, especialmente si está familiarizado con la función, pero por lo general requiere volver a mirar. OTOH,

 [(1,2), (3,1), (5,10), (11,-3)].sort(lambda x: x[1]) 

te dice mucho mas

  1. Ordenar toma una función como argumento
  2. Esa función toma 1 parámetro (y “devuelve” un resultado)
  3. Estoy tratando de ordenar esta lista por el segundo valor de cada uno de los elementos de la lista
  4. (Si la lista fuera una variable para que no pudiera ver los valores), esta lógica espera que la lista tenga al menos 2 elementos.

Probablemente haya más información, pero ya es una cantidad tremenda que se obtiene al usar una función lambda anónima en lugar de una función nombrada.

Además, no contamina su espacio de nombres;)

Para mí es cuestión de la expresividad del código. Al escribir un código que la gente tendrá que apoyar, ese código debe contar una historia de la manera más concisa y fácil de entender que sea posible. A veces, la expresión lambda es más complicada, otras veces dice más directamente qué está haciendo esa línea o bloque de código. Usa el juicio al escribir.

Piense en ello como estructurar una oración. ¿Cuáles son las partes importantes (sustantivos y verbos frente a objetos y métodos, etc.) y cómo se deben ordenar para esa línea o bloque de código para transmitir lo que está haciendo de manera intuitiva?

Sí, tienes razón, es una elección estructural. Probablemente no haga que sus progtwigs sean más correctos con solo usar expresiones lambda. Tampoco los hace más confiables, y esto no tiene nada que ver con la velocidad.

Se trata solo de la flexibilidad y el poder de expresión. Me gusta la comprensión de listas. Puede hacer la mayor parte de esa definición de funciones nombradas (posiblemente el espacio de nombres contaminante, pero eso es nuevamente un problema puramente estilístico).

Puede ayudar a la legibilidad por el hecho de que no tiene que definir una función nombrada por separado, que otra persona tendrá que encontrar, leer y comprender que todo lo que hace es llamar a un método blah () en su argumento.

Puede ser mucho más interesante cuando lo usa para escribir funciones que crean y devuelven otras funciones, donde lo que hacen exactamente esas funciones depende de sus argumentos. Esta puede ser una forma muy concisa y legible de parametrizar el comportamiento de su código. Puedes express ideas más interesantes.

Pero eso sigue siendo una opción estructural. Puedes hacerlo de otra manera. Pero lo mismo ocurre con la progtwigción orientada a objetos;)

Ignore por un momento el detalle de que se trata de funciones específicamente anónimas. Las funciones, incluidas las anónimas, son cantidades asignables (casi, pero no realmente, valores) en Python. una expresión como

 map(lambda y: y * -1, range(0, 10)) 

menciona explícitamente cuatro cantidades anónimas: -1, 0, 10 y el resultado del operador lambda, más el resultado implícito de la llamada del map . Es posible crear valores de tipos anónimos en algunos idiomas. así que ignora la diferencia superficial entre funciones y números. la pregunta de cuándo usar una función anónima en lugar de la que tiene un nombre es similar a la pregunta de cuándo colocar un número desnudo literal en el código y cuándo declarar un TIMES_I_WISHED_I_HAD_A_PONY o BUFFER_SIZE antemano. hay ocasiones en que es apropiado usar un literal (numérico, de cadena o función), y hay ocasiones en que es más apropiado nombrar tal cosa y referirse a ella a través de su nombre.

ver por ejemplo El libro provocativo y provocativo de Allen Holub sobre los patrones de diseño en Java; Él usa clases anónimas un poco.

Un uso de la función lambda que he aprendido, y donde no es otra buena alternativa o al menos me busca mejor, es como acción predeterminada en el parámetro de función de

 parameter=lambda x: x 

Esto devuelve el valor sin cambios, pero puede proporcionar una función opcionalmente para realizar una transformación o acción (como imprimir la respuesta, no solo regresar)

También a menudo es útil utilizar en la clasificación como clave:

 key=lambda x: x[field] 

El efecto es ordenar por campo el elemento (recordatorio basado en cero) de cada elemento en secuencia. Para invertir no necesita lambda ya que es más claro de usar

 reverse=True 

A menudo es casi tan fácil hacer una nueva función real y usar eso en lugar de lambda. Si las personas han estudiado mucho Lisp u otra progtwigción funcional, también tienen una tendencia natural a usar la función lambda, ya que en Lisp las definiciones de funciones son manejadas por el cálculo lambda.

Lambda, aunque es útil en ciertas situaciones, tiene un gran potencial de abuso. lambda casi siempre hace que el código sea más difícil de leer. Y aunque puede parecer satisfactorio encajar todo su código en una sola línea, será un asco para la siguiente persona que tenga que leer su código.

Directo desde PEP8

“Una de las ideas clave de Guido es que el código se lee mucho más a menudo que lo que está escrito”.

Las Lambdas son objetos, no métodos, y no pueden invocarse de la misma manera que lo son los métodos. por ejemplo

 succ = ->(x){ x+1 } 

succ mow contiene un objeto Proc, que podemos usar como cualquier otro:

 succ.call(2) 

nos da una salida = 3

En algunos casos es mucho más claro express algo simple como un lambda. Considere la clasificación regular frente a la clasificación inversa, por ejemplo:

 some_list = [2, 1, 3] print sorted(some_list) print sorted(some_list, lambda a, b: -cmp(a, b)) 

Para el último caso, escribir una función completa de pleno derecho solo para devolver un -cmp(a, b) crearía más malentendidos que un lambda.

Quiero señalar una situación distinta del procesamiento de listas donde las funciones lambda parecen la mejor opción:

 from tkinter import * from tkinter import ttk def callback(arg): print(arg) pass root = Tk() ttk.Button(root, text = 'Button1', command = lambda: callback('Button 1 clicked')).pack() root.mainloop() 

Y si eliminamos la función lambda aquí, la callback solo puede ejecutar la callback una vez.

 ttk.Button(root, text = 'Button1', command = callback('Button1 clicked')).pack() 

Las Lambdas son funciones anónimas (función sin nombre) que se pueden asignar a una variable o que se pueden pasar como un argumento a otra función. La utilidad de Lambda se realizará cuando necesite una pequeña parte de la función que se ejecutará una de vez en cuando o solo una vez. En lugar de escribir la función en el ámbito global o incluirla como parte de su progtwig principal, puede lanzar algunas líneas de código cuando sea necesario a una variable u otra función. Además, cuando pasa la función como un argumento a otra función durante la llamada a la función, puede cambiar el argumento (la función anónima) haciendo que la función en sí sea dinámica. Supongamos que si la función anónima usa variables fuera de su scope se llama cierre. Esto es útil en las funciones de callback.

Otro punto es que Python no tiene instrucciones de cambio. Combinar las lambdas con los dados puede ser una alternativa efectiva. p.ej:

 switch = { '1': lambda x: x+1, '2': lambda x: x+2, '3': lambda x: x+3 } x = starting_val ans = expression new_ans = switch[ans](x) 

Lambdas te permite crear funciones sobre la marcha. La mayoría de los ejemplos que he visto no hacen mucho más que crear una función con parámetros pasados ​​en el momento de la creación en lugar de la ejecución. O simplifican el código al no requerir una statement formal de la función antes de su uso.

Un uso más interesante sería construir dinámicamente una función de python para evaluar una expresión matemática que no se conoce hasta el tiempo de ejecución (entrada del usuario). Una vez creada, se puede llamar a esa función repetidamente con diferentes argumentos para evaluar la expresión (digamos que desea dibujarla). Eso puede incluso ser un mal ejemplo dado eval (). Este tipo de uso es donde está el poder “real”: en la creación dinámica de código más complejo, en lugar de los simples ejemplos que a menudo se ven, que no son mucho más que agradables reducciones de tamaño de código (fuente).