usar sintaxis propias funciones funcion español ejemplos ejemplo como python syntax function lambda

sintaxis - lambda python 3 español



¿Qué es más preferible usar en Python: funciones lambda o funciones anidadas(''def'')? (15)

Más preferible: funciones lambda o funciones anidadas ( def )?

Hay una ventaja de usar una lambda sobre una función normal (se crean en una expresión) y varios inconvenientes. Por esa razón, prefiero crear funciones con la palabra clave def lugar de con lambdas.

Primer punto: son el mismo tipo de objeto

Una lambda da como resultado el mismo tipo de objeto que una función regular

>>> l = lambda: 0 >>> type(l) <class ''function''> >>> def foo(): return 0 ... >>> type(foo) <class ''function''> >>> type(foo) is type(l) True

Como las lambdas son funciones, son objetos de primera clase.

Ambos lambdas y funciones:

  • se puede pasar como un argumento (igual que una función normal)
  • cuando se crea dentro de una función externa se convierte en un cierre sobre los locales locales de las funciones externas

Pero las lambdas, de forma predeterminada, faltan algunas cosas que las funciones obtienen a través de la sintaxis de definición de función completa.

El __name__ un lamba es ''<lambda>''

Las lambdas son funciones anónimas, después de todo, por lo que no conocen su propio nombre.

>>> l.__name__ ''<lambda>'' >>> foo.__name__ ''foo''

Por lo tanto, lambda no se puede buscar programáticamente en su espacio de nombres.

Esto limita ciertas cosas. Por ejemplo, foo se puede buscar con código serializado, mientras que no puedo:

>>> import pickle >>> pickle.loads(pickle.dumps(l)) Traceback (most recent call last): File "<stdin>", line 1, in <module> _pickle.PicklingError: Can''t pickle <function <lambda> at 0x7fbbc0464e18>: attribute lookup <lambda> on __main__ failed

Podemos buscar bien, porque conoce su propio nombre:

>>> pickle.loads(pickle.dumps(foo)) <function foo at 0x7fbbbee79268>

Lambdas no tiene anotaciones y no docstring

Básicamente, las lambdas no están documentadas. Vamos a reescribir foo para que esté mejor documentado:

def foo() -> int: """a nullary function, returns 0 every time""" return 0

Ahora, foo tiene documentación:

>>> foo.__annotations__ {''return'': <class ''int''>} >>> help(foo) Help on function foo in module __main__: foo() -> int a nullary function, returns 0 every time

Mientras que, no tenemos el mismo mecanismo para dar la misma información a lambdas:

>>> help(l) Help on function <lambda> in module __main__: <lambda> lambda (...)

Pero podemos hackearlos:

>>> l.__doc__ = ''nullary -> 0'' >>> l.__annotations__ = {''return'': int} >>> help(l) Help on function <lambda> in module __main__: <lambda> lambda ) -> in nullary -> 0

Pero probablemente haya algún error que arruine el resultado de la ayuda.

Lambdas solo puede devolver una expresión

Lambdas no puede devolver declaraciones complejas, solo expresiones.

>>> lambda: if True: 0 File "<stdin>", line 1 lambda: if True: 0 ^ SyntaxError: invalid syntax

Es cierto que las expresiones pueden ser bastante complejas, y si lo intenta con todas sus fuerzas, probablemente logre lo mismo con una lambda, pero la complejidad adicional es más perjudicial que escribir código claro.

Usamos Python para mayor claridad y facilidad de mantenimiento. El uso excesivo de lambdas puede funcionar en contra de eso.

La única ventaja para lambdas: se puede crear en una sola expresión

Esta es la única ventaja posible. Como puede crear una lambda con una expresión, puede crearla dentro de una llamada a función.

Crear una función dentro de una llamada de función evita la búsqueda de nombres (de bajo costo) en comparación con uno creado en otro lugar.

Sin embargo, dado que Python se evalúa estrictamente, no hay otra ganancia de rendimiento al hacerlo, además de evitar la búsqueda de nombres.

Para una expresión muy simple, podría elegir una lambda.

También tiendo a usar lambdas cuando hago Python interactivo, para evitar líneas múltiples cuando uno lo hace. Uso el siguiente tipo de formato de código cuando quiero pasar un argumento a un constructor al llamar a timeit.repeat :

import timeit def return_nullary_lambda(return_value=0): return lambda: return_value def return_nullary_function(return_value=0): def nullary_fn(): return return_value return nullary_fn

Y ahora:

>>> min(timeit.repeat(lambda: return_nullary_lambda(1))) 0.24312214995734394 >>> min(timeit.repeat(lambda: return_nullary_function(1))) 0.24894469301216304

Creo que la pequeña diferencia de tiempo anterior se puede atribuir a la búsqueda de nombre en return_nullary_function . return_nullary_function en cuenta que es muy insignificante.

Conclusión

Las lambdas son buenas para situaciones informales donde se desea minimizar las líneas de código a favor de hacer un punto singular.

Las lambdas son malas para situaciones más formales donde se necesita claridad para los editores de código que vendrán después, especialmente en los casos en que no son triviales.

Sabemos que debemos darles buenos nombres a nuestros objetos. ¿Cómo podemos hacer eso cuando el objeto no tiene nombre?

Por todas estas razones, prefiero crear funciones con def lugar de con lambda .

Uso principalmente funciones lambda, pero a veces uso funciones anidadas que parecen proporcionar el mismo comportamiento.

Aquí hay algunos ejemplos triviales donde funcionalmente hacen lo mismo si se encuentran dentro de otra función:

Función Lambda

>>> a = lambda x : 1 + x >>> a(5) 6

Función anidada

>>> def b(x): return 1 + x >>> b(5) 6

¿Hay ventajas al usar una sobre la otra? (Rendimiento? ¿Legibilidad? ¿Limitaciones? ¿Consistencia? Etc.)

¿Incluso importa? Si no lo hace, eso viola el principio Pythonic:

"Debería haber una, y preferiblemente solo una, forma obvia de hacerlo" .


El uso principal de lambda siempre ha sido para funciones de devolución de llamada simples, y para map, reduce, filter, que requieren una función como argumento. Con la lista de comprensiones convirtiéndose en la norma, y ​​el agregado permitido si como en:

x = [f for f in range(1, 40) if f % 2]

es difícil imaginar un caso real para el uso de lambda en el uso diario. Como resultado, yo diría que evite lambda y cree funciones anidadas.


En términos prácticos, para mí hay dos diferencias:

El primero es sobre lo que hacen y lo que devuelven:

  • def es una palabra clave que no devuelve nada y crea un ''nombre'' en el espacio de nombres local.

  • lambda es una palabra clave que devuelve un objeto de función y no crea un ''nombre'' en el espacio de nombres local.

Por lo tanto, si necesita llamar a una función que toma un objeto de función, la única forma de hacerlo en una línea de código python es con una lambda. No hay equivalente con def.

En algunos marcos esto es realmente bastante común; por ejemplo, uso mucho Twisted , y hago algo así como

d.addCallback(lambda result: setattr(self, _someVariable, result))

es bastante común y más conciso con lambdas.

La segunda diferencia es acerca de lo que se permite hacer la función real.

  • Una función definida con ''def'' puede contener cualquier código python
  • Una función definida con ''lambda'' tiene que evaluar a una expresión, y por lo tanto no puede contener declaraciones como imprimir, importar, aumentar, ...

Por ejemplo,

def p(x): print x

funciona como se esperaba, mientras

lambda x: print x

es un SyntaxError.

Por supuesto, existen soluciones alternativas: sustitúyalo por sys.stdout.write o import por __import__ . Pero por lo general es mejor ir con una función en ese caso.


Estoy de acuerdo con el consejo de nosklo: si necesitas darle un nombre a la función, usa def . Yo reservo funciones lambda para casos en los que solo estoy pasando un breve fragmento de código a otra función, por ejemplo:

a = [ (1,2), (3,4), (5,6) ] b = map( lambda x: x[0]+x[1], a )


Estoy de acuerdo con nosklo. Por cierto, incluso con una función de uso una vez, tirar , la mayoría de las veces solo quieres usar algo del módulo de operador.

P.EJ :

Usted tiene una función con esta firma: myFunction (datos, función de devolución de llamada).

Desea pasar una función que agrega 2 elementos.

Usando lambda:

myFunction(data, (lambda x, y : x + y))

La manera pitónica:

import operator myFunction(data, operator.add)

Por supuesto, este es un ejemplo simple, pero hay muchas cosas que proporciona el módulo operador, incluidos los elementos setters / getters para list y dict. Realmente genial.


Para n = 1000, aquí hay un tiempo de invocación de una función frente a una lambda:

In [11]: def f(a, b): return a * b In [12]: g = lambda x, y: x * y In [13]: %%timeit -n 100 for a in xrange(n): for b in xrange(n): f(a, b) ....: 100 loops, best of 3: 285 ms per loop In [14]: %%timeit -n 100 for a in xrange(n): for b in xrange(n): g(a, b) ....: 100 loops, best of 3: 298 ms per loop In [15]: %%timeit -n 100 for a in xrange(n): for b in xrange(n): (lambda x, y: x * y)(a, b) ....: 100 loops, best of 3: 462 ms per loop


Si bien está de acuerdo con las otras respuestas, a veces es más legible. Aquí hay un ejemplo donde lambda es útil, en un caso de uso me encuentro con un N defaultdict dimensional.
Aquí hay un ejemplo:

from collections import defaultdict d = defaultdict(lambda: defaultdict(list)) d[''Foo''][''Bar''].append(something)

Me resulta más legible que crear una def para la segunda dimensión. Esto es aún más significativo para dimensiones más altas.


Si necesita asignar la lambda a un nombre, use una def lugar. def s son solo azúcar sintáctica para una tarea, por lo que el resultado es el mismo, y son mucho más flexibles y legibles.

lambda pueden usarse una vez, desechar funciones que no tendrán nombre.

Sin embargo, este caso de uso es muy raro. Rara vez necesita pasar objetos de función sin nombre.

El map() incorporado map() y el filter() necesitan objetos de función, pero las listas de comprensión y las expresiones del generador son generalmente más legibles que esas funciones y pueden abarcar todos los casos de uso, sin la necesidad de lambdas.

Para los casos en los que realmente necesita un pequeño objeto de función, debe usar las funciones del módulo de operator , como operator.add lugar de lambda x, y: x + y

Si aún necesita alguno lambda no cubierto, puede considerar escribir una def , solo para ser más legible. Si la función es más compleja que las del módulo operator , una def es probablemente mejor.

Entonces, los casos de uso de lambda mundo real son muy raros.


Si va a asignar la lambda a una variable en el ámbito local, también puede usar def porque es más legible y se puede expandir más fácilmente en el futuro:

fun = lambda a, b: a ** b # a pointless use of lambda map(fun, someList)

o

def fun(a, b): return a ** b # more readable map(fun, someList)


Un uso para lambdas que he encontrado ... está en los mensajes de depuración.

Como lambdas se puede evaluar de forma perezosa, puedes tener un código como este:

log.debug(lambda: "this is my message: %r" % (some_data,))

en lugar de posiblemente costoso:

log.debug("this is my message: %r" % (some_data,))

que procesa la cadena de formato incluso si la llamada de depuración no produce salida debido al nivel de registro actual.

Por supuesto, para que funcione como se describe, el módulo de registro en uso debe admitir lambdas como "parámetros vagos" (como lo hace mi módulo de registro).

La misma idea se puede aplicar a cualquier otro caso de evaluación perezosa para la creación de valor de contenido bajo demanda.

Por ejemplo, este operador ternario personalizado:

def mif(condition, when_true, when_false): if condition: return when_true() else: return when_false() mif(a < b, lambda: a + a, lambda: b + b)

en lugar de:

def mif(condition, when_true, when_false): if condition: return when_true else: return when_false mif(a < b, a + a, b + b)

con lambdas solo se evaluará la expresión seleccionada por la condición, sin lambdas ambos serán evaluados.

Por supuesto, podría simplemente usar funciones en lugar de lambdas, pero para expresiones cortas las lambdas son (c) más delgadas.


Una gran diferencia es que no puede usar las funciones def línea, que en mi opinión es el caso de uso más conveniente para una función lambda . Por ejemplo, al ordenar una lista de objetos:

my_list.sort(key=lambda o: o.x)

Por lo tanto, sugiero que se mantenga el uso de lambdas en este tipo de operaciones triviales, que tampoco se benefician realmente con la documentación automática proporcionada al nombrar la función.


Una limitación importante de lambdas es que no pueden contener nada más que una expresión. Es casi imposible que una expresión lambda produzca algo más que efectos secundarios triviales, ya que no puede tener un cuerpo tan rico como una función definida.

Dicho esto, Lua influyó en mi estilo de programación hacia el uso extensivo de funciones anónimas, y llené mi código con ellas. Además de eso, tiendo a pensar sobre el mapa / reducir como operadores abstractos en formas que no considero listas de comprensión o generadores, casi como si estuviera difiriendo explícitamente una decisión de implementación mediante el uso de esos operadores.

Editar: Esta es una pregunta muy antigua, y mis opiniones sobre el tema han cambiado, de alguna manera.

En primer lugar, estoy muy predispuesto a no asignar una expresión lambda a una variable; como python tiene una sintaxis especial solo para eso (pista, def ). Además de eso, muchos de los usos de lambda, incluso cuando no tienen un nombre, tienen implementaciones predefinidas (y más eficientes). Por ejemplo, el ejemplo en cuestión se puede abreviar a simplemente (1).__add__ , sin la necesidad de envolverlo en un lambda o def . Muchos otros usos comunes se pueden satisfacer con una combinación de los módulos operator , itertools y functools .


lambda es útil para generar nuevas funciones:

def somefunc(x): return lambda y: x+y f = somefunc(10) f(2) >>> 12 f(4) >>> 14


En esta entrevista, Guido van Rossum dice que desearía no haber permitido que ''lambda'' entrara en Python:

" P. ¿Con qué característica de Python está menos satisfecho?

A veces he sido demasiado rápido para aceptar contribuciones, y luego me di cuenta de que era un error. Un ejemplo sería algunas de las funciones de programación funcional, como las funciones lambda. lambda es una palabra clave que le permite crear una pequeña función anónima; las funciones integradas como mapa, filtro y reducir ejecutan una función sobre un tipo de secuencia, como una lista.

En la práctica, no resultó tan bien. Python solo tiene dos ámbitos: local y global. Esto hace que escribir funciones lambda sea doloroso, porque a menudo desea acceder a las variables en el ámbito donde se definió el lambda, pero no puede hacerlo debido a los dos ámbitos. Hay una forma de evitar esto, pero es una especie de kludge. A menudo, en Python parece mucho más fácil usar un bucle for en lugar de jugar con las funciones lambda. el mapa y los amigos funcionan bien solo cuando ya hay una función incorporada que hace lo que quieres.

En mi humilde opinión, Iambdas puede ser conveniente a veces, pero por lo general son convenientes a expensas de la legibilidad. ¿Puedes decirme qué hace esto?

str(reduce(lambda x,y:x+y,map(lambda x:x**x,range(1,1001))))[-10:]

Lo escribí, y me llevó un minuto resolverlo. Esto es del Proyecto Euler - no diré qué problema porque odio los spoilers, pero se ejecuta en 0.124 segundos :)


Actuación:

Crear una función con lambda es ligeramente más rápido que crearlo con def . La diferencia se debe a la creación de una entrada de nombre en la tabla locales. La función resultante tiene la misma velocidad de ejecución.

Legibilidad:

Las funciones de Lambda son algo menos legibles para la mayoría de los usuarios de Python, pero también mucho más concisas en algunas circunstancias. Considere la posibilidad de convertir el uso de la rutina no funcional a funcional:

# Using non-functional version. heading(math.sqrt(v.x * v.x + v.y * v.y), math.atan(v.y / v.x)) # Using lambda with functional version. fheading(v, lambda v: math.sqrt(v.x * v.x + v.y * v.y), lambda v: math.atan(v.y / v.x)) # Using def with functional version. def size(v): return math.sqrt(v.x * v.x + v.y * v.y) def direction(v): return math.atan(v.y / v.x) deal_with_headings(v, size, direction)

Como puede ver, la versión de lambda es más corta y "más fácil" en el sentido de que solo necesita agregar lambda v: a la versión original no funcional para convertirla a la versión funcional. También es mucho más conciso. Pero recuerde, muchos usuarios de Python se confundirán con la sintaxis lambda, por lo que lo que pierda en longitud y complejidad real podría volverse confuso por parte de otros codificadores.

Limitaciones

  • lambda funciones lambda solo se pueden usar una vez, a menos que estén asignadas a un nombre de variable.
  • lambda funciones lambda asignadas a nombres variables no tienen ninguna ventaja sobre las funciones def .
  • lambda funciones lambda pueden ser difíciles o imposibles de encurtir.
  • Los nombres de las funciones def deben elegirse cuidadosamente para que sean razonablemente descriptivos y únicos, o al menos no se usen en su alcance.

Consistencia:

Python generalmente evita las convenciones de programación funcional a favor de la semántica objetiva de procedimientos y más simple. El operador lambda está en contraste directo con este sesgo. Además, como alternativa a la def ya prevalente, la función lambda agrega diversidad a su sintaxis. Algunos considerarían que menos consistente.

Funciones preexistentes:

Como notaron otros, muchos usos de lambda en el campo pueden ser reemplazados por miembros del operator u otros módulos. Por ejemplo:

do_something(x, y, lambda x, y: x + y) do_something(x, y, operator.add)

El uso de la función preexistente puede hacer que el código sea más legible en muchos casos.

El principio Pythonic: "Debería haber una, y preferiblemente solo una, forma obvia de hacerlo"

Eso es similar a la fuente única de la doctrina de la verdad . Desafortunadamente, el principio de la única y obvia manera de hacerlo siempre ha sido más una aspiración melancólica para Python que un verdadero principio rector. Considere la gran variedad de comprensiones en Python. Son funcionalmente equivalentes a las funciones de map y filter :

[e for e in some_array if some_condition(e)] filter(some_array, some_condition)

lambda y def son lo mismo.

Es una cuestión de opinión, pero diría que cualquier cosa en el lenguaje Python para uso general que obviamente no rompa nada es lo suficientemente "pitónico".