¿Alguien puede explicar las razones concretas por las que BDFL elige hacer una línea única de Python lambdas?
Esto es bueno:
lambda x: x**x
Esto da como resultado un error:
lambda x:
x**x
Entiendo que hacer que lambda sea multilínea de alguna manera "perturbaría" las reglas de sangría normales y requeriría agregar más excepciones, pero ¿no vale la pena los beneficios?
Mire JavaScript, por ejemplo. ¿Cómo se puede vivir sin esas funciones anónimas? Son indispensables ¿No quieren los Pythonistas deshacerse de tener que nombrar cada función de varias líneas solo para pasarla como argumento?
def
? Ahora tiene exactamente la misma estructura visual.Respuestas:
Guido van van Rossum lo respondió él mismo:
http://www.artima.com/weblogs/viewpost.jsp?thread=147358
Básicamente, dice que aunque una solución es posible, no es congruente con cómo es Python.
fuente
está perfectamente bien hacer un lambda multilínea en python: ver
La verdadera limitación lambda es el hecho de que lambda debe ser una sola expresión ; no puede contener palabras clave (como python2's
print
oreturn
).GvR elige hacerlo para limitar el tamaño de la lambda, ya que normalmente se usan como parámetros. Si quieres una función real, usa
def
fuente
def
. Piénselo: ¿realmente necesita un invocable como parámetro de su función? ¿Y a los usuarios de esa función no se les permite pasar su llamada predeterminada? ¿Cómo pueden pasarlo si no se lo das?Sé que esto es muy antiguo, pero lo pongo aquí como referencia.
Una alternativa al uso de lambda podría ser usar a
def
de una manera no convencional. El objetivo es pasar unadef
función a, lo que se puede hacer en una sola circunstancia: un decorador. Tenga en cuenta que con esta implementacióndef result
no crea una función, crea el resultado dereduce()
, que termina siendo adict
.Enchufe desvergonzado : hago mucho de esto aquí .
Tenga en cuenta que se pueden hacer lambdas de varias declaraciones , pero solo con un código realmente muy feo. Sin embargo, lo interesante es cómo funciona el alcance con esta implementación (tenga en cuenta el uso múltiple de la
name
variable y el sombreado de lamessage
variable.fuente
Hackear juntos una lambda de múltiples declaraciones no es tan malo como lo hace Pyrospade: seguro que podríamos componer un montón de funciones monádicas usando bind, como en Haskell, pero como estamos en el mundo impuro de Python, también podríamos usa efectos secundarios para lograr lo mismo.
Cubro algunas maneras de hacer esto en mi blog .
Por ejemplo, Python garantiza evaluar los elementos de una tupla en orden, por lo que podemos usarlo
,
como un imperativo;
. Podemos reemplazar muchas declaraciones, likeprint
, con expresiones, likesys.stdout.write
.Por lo tanto, los siguientes son equivalentes:
Tenga en cuenta que agregué un
None
al final y lo extraje usando[-1]
; Esto establece el valor de retorno explícitamente. No tenemos que hacer esto, pero sin él obtendríamos un(None, None, None)
valor de retorno funky , que nos puede interesar o no.Entonces podemos secuenciar acciones IO. ¿Qué pasa con las variables locales?
Python
=
forma una declaración, por lo que necesitamos encontrar una expresión equivalente. Una forma es mutar el contenido de la estructura de datos, que se pasa como argumento. Por ejemplo:Hay algunos trucos que se utilizan en
stateful_lambda
:*_
argumento permite que nuestra lambda tome cualquier número de argumentos. Como esto permite cero argumentos, recuperamos la convención de llamada destateful_def
._
es solo una convención que dice "No voy a usar esta variable"lambda state: lambda *_: ...
(lambda state: ...)({})
state
a un valor{}
sin usar una declaración de asignación (p. Ej.state = {}
)state
como nombres de variables y valores enlazados.state.setdefault(a, b)
lugar dea = b
y enstate.get(a)
lugar dea
[-1]
para extraer el último valor, que actúa como unareturn
declaraciónPor supuesto, esto es bastante engorroso, pero podemos hacer una API más agradable con funciones auxiliares:
fuente
Pensé que podría contribuir, use un interruptor de línea:
No olvides lo muy bueno que Python puede escribir en líneas, como en el ejemplo:
Y el lambda es muy poderoso, pero no está destinado a la sustitución de 1 función completa, es decir, podría piratearlo como (ejemplo de préstamo del colega anterior):
¿Pero realmente quieres hacerlo así? En su mayoría es ilegible después de algún tiempo, es como llegar al comienzo de la cuerda comenzando con el final desenredado.
Las lambdas se consideran funciones únicas, en el mapa, filtran y reducen funciones en la programación orientada funcional (entre otras cosas). Por ejemplo, obtener valores de caracteres de valores que son enteros y divisibles por 2
Puede usarlo como función de expresión de funciones definiendo funciones complejas (o más y varias lambdas, y colocándolas dentro de otra lambda:
pero Python tiene soporte para expresiones de funciones de otra manera: -let dice que tiene alguna función llamada
superAwesomeFunction
y esa función puede hacer cosas súper increíbles, puede asignarla a una variable al no llamarla, así:Entonces, cuando llame a SAF, llamará a superAwesomeFunction o método. Si busca a través de su carpeta Lib, puede encontrar que la mayoría de los
__builtin__
módulos de Python están escritos de esa manera. Esto se hace porque a veces necesitará algunas funciones que realicen tareas específicas que no son lo suficientemente necesarias para que el usuario pueda usarlas, pero es necesario para varias funciones. Entonces, tiene la opción de no tener 2 funciones con el nombre "superAwesomeFunction", puede tener "superAwesomeFunctionDoingBasicStuf" y "realSuperAwesomeFunction" y simplemente poner la variable "realSuperAwesomeFunction" en "superAwesomeFunction" y listo.Puede encontrar la ubicación de los módulos importados ingresando en la consola
importedModule.__file__
(ejemplo realimport os;os.__file__
), y simplemente siga ese directorio al archivo llamado importModule.py y ábralo en el editor y descubra cómo puede maximizar su propio "conocimiento".Espero que esto te ayude a ti y quizás a otros colegas en problemas.
fuente