python - funcion - porque usar lambda aws
¿Por qué usar las funciones lambda? (14)
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 programación, particularmente en programación funcional, de los cuales el cálculo lambda proporcionó la inspiración.
Puedo encontrar muchas cosas que me muestran qué es una función lambda, y cómo funciona la sintaxis y qué no. Pero aparte del "factor coolness" (puedo hacer una función en el medio de una llamada a otra función, ¡perfecto!) No he visto algo que sea demasiado convincente para decir por qué realmente los necesito / quiero usar.
Parece ser una elección más estilística o estructural en la mayoría de los ejemplos que he visto. Y rompe un poco la "Única forma correcta de hacer algo" en la regla de Python. ¿Cómo hace que mis programas 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 codificación que he visto tienden a decirle que evite declaraciones excesivamente complejas en una sola línea. Si es más fácil leerlas, divídalas).
En algunos casos, es mucho más claro expresar 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 este último caso, escribir una función separada completa para devolver un -cmp(a, b)
crearía más malentendidos que una lambda.
Ignore por un momento el detalle de que son funciones específicamente anónimas de las que estamos hablando. 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 al 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 sobre cuándo usar una función anónima en lugar de una nombrada es similar a la pregunta de cuándo poner un número desnudo literal en el código y cuándo declarar TIMES_I_WISHED_I_HAD_A_PONY
o BUFFER_SIZE
antemano. hay momentos en los que es apropiado usar un literal (numérico, de cadena o de función), y hay momentos en los que es más apropiado nombrar tal cosa y referirse a ella a través de su nombre.
ver por ej. El provocador libro de Allen Holub sobre pensamiento y provocación de ira en Design Patterns in Java; usa clases anónimas bastante.
La sintaxis 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 el def double
parece estar casi desconectado del map
que lo está usando. Además, creo que tiene el beneficio adicional de que la función se descarta cuando termina.
Hay una desventaja de lambda que limita su utilidad en Python, en mi opinión: lambdas puede tener una sola expresión (es decir, no puede tener varias líneas). Simplemente no puede funcionar en un lenguaje que fuerza el espacio en blanco.
Además, cada vez que uso lambda me siento increíble.
Lambda, si bien 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 si bien puede ser satisfactorio ajustar todo tu código en una sola línea, será una mierda para la próxima persona que tenga que leer tu código.
Directo desde PEP8
"Una de las ideas clave de Guido es que el código se lee con mucha más frecuencia de lo que está escrito".
Lambdas son funciones anónimas (función sin nombre) que se pueden asignar a una variable o que se pueden pasar como argumento a otra función. La utilidad de lambda se realizará cuando necesite una pequeña función que se ejecutará de a una por vez o solo una vez. En lugar de escribir la función en un ámbito global o incluirla como parte de su programa principal, puede lanzar algunas líneas de código cuando sea necesario para una variable u otra función. Además, cuando pasa la función como 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 sea dinámica. Supongamos que si la función anónima usa variables fuera de su alcance se llama cierre. Esto es útil en las funciones de devolución de llamada.
Lambdas son objetos, no métodos, y no se pueden invocar de la misma manera que 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 un resultado = 3
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 declaración formal de la función antes del uso.
Un uso más interesante sería construir dinámicamente una función python para evaluar una expresión matemática que no se conoce hasta el tiempo de ejecución (entrada del usuario). Una vez creada, esa función se puede invocar repetidamente con diferentes argumentos para evaluar la expresión (digamos que se quería trazar). Eso incluso puede ser un mal ejemplo dado eval (). Este tipo de uso es donde se encuentra el poder "real": al crear dinámicamente código más complejo, en lugar de los ejemplos simples que a menudo se ven y que no son mucho más que bonitas reducciones de tamaño del código (fuente).
Las funciones de Lambda son más útiles en cosas como funciones de devolución de llamada o lugares en los que necesita una función de descarte. El ejemplo de JAB es perfecto: estaría mejor acompañado de 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)
que hace la llave? Realmente no hay 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 más.
- Sort toma una función como argumento
- Esa función toma 1 parámetro (y "devuelve" un resultado)
- Estoy tratando de ordenar esta lista por el segundo valor de cada uno de los elementos de la lista
- (Si la lista era una variable para que no se pudieran ver los valores), esta lógica espera que la lista tenga al menos 2 elementos.
Probablemente haya algo más de información, pero ya es una gran cantidad que obtienes simplemente usando una función lambda anónima en lugar de una función con nombre.
Además, no contamina su espacio de nombres;)
Otro punto es que python no tiene declaraciones de cambio. La combinación de lambdas con dicts 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)
Para mí, es una cuestión de expresividad del código. Al escribir un código que la gente tendrá que respaldar, ese código debe contar una historia de la manera más concisa y fácil de entender posible. A veces, la expresión lambda es más complicada, otras veces indica de manera más directa 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 deberían ordenarse para esa línea o bloque de código para transmitir lo que está haciendo intuitivamente?
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 dejamos la función lambda aquí, la devolución de llamada solo puede ejecutar la devolución de llamada una vez.
ttk.Button(root, text = ''Button1'', command = callback(''Button1 clicked'')).pack()
Sí, tienes razón, es una elección estructural. Probablemente no haga que sus programas sean más correctos simplemente usando 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 la expresión. Como lista de comprensión. Puedes hacer la mayoría de esas funciones nombradas definitorias (posiblemente un 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 alguien más 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 exactamente lo que hacen esas funciones depende de sus argumentos. Esta puede ser una forma muy concisa y legible de parametrizar el comportamiento de su código. Puedes simplemente expresar ideas más interesantes.
Pero esa sigue siendo una elección estructural. Puedes hacer eso de lo contrario. Pero lo mismo ocurre con la programación orientada a objetos;)
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 por
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 devolverla)
También a menudo es útil usarlo en la clasificación como clave:
key=lambda x: x[field]
El efecto es ordenar por elemento fieldth (recordar basado en cero) de cada elemento en secuencia. Para invertir, no necesita lambda ya que es más claro usar
reverse=True
A menudo es casi tan fácil hacer una nueva función real y usarla en lugar de lambda. Si las personas han estudiado mucho Lisp u otra programación funcional, también tienen una tendencia natural a utilizar la función lambda, ya que en Lisp las definiciones de funciones se manejan mediante cálculo lambda.