He oído decir que no se pueden agregar lambdas multilínea en Python porque chocarían sintácticamente con las otras construcciones de sintaxis en Python. Hoy estaba pensando en esto en el autobús y me di cuenta de que no podía pensar en una sola construcción de Python con la que las lambdas multilínea chocaran. Dado que conozco bastante bien el idioma, esto me sorprendió.
Ahora, estoy seguro de que Guido tenía una razón para no incluir lambdas multilínea en el idioma, pero por curiosidad: ¿cuál es la situación en la que incluir una lambda multilínea sería ambiguo? ¿Es cierto lo que he escuchado, o hay alguna otra razón por la que Python no permite lambdas multilínea?
lambda
expresiones en primer lugar; simplemente podría usardef
declaraciones en expresiones.Respuestas:
Mira lo siguiente:
¿Es esto un retorno de lambda
(y, [1,2,3])
(por lo tanto, el mapa solo obtiene un parámetro, lo que resulta en un error)? ¿O vuelvey
? ¿O es un error de sintaxis, porque la coma en la nueva línea está fuera de lugar? ¿Cómo sabría Python lo que quieres?Dentro de los parens, la sangría no es importante para Python, por lo que no puede trabajar sin ambigüedades con líneas múltiples.
Este es solo uno simple, probablemente haya más ejemplos.
fuente
Guido van Rossum (el inventor de Python) responde a esta pregunta exacta él mismo en una antigua publicación de blog .
Básicamente, admite que es teóricamente posible, pero que cualquier solución propuesta no sería Pythonic:
fuente
Esto generalmente es muy feo (pero a veces las alternativas son aún más feas), por lo que una solución alternativa es hacer una expresión de llaves:
Sin embargo, no aceptará ninguna tarea, por lo que deberá preparar los datos de antemano. El lugar donde encontré esto útil es el contenedor PySide, donde a veces tienes devoluciones de llamada cortas. Escribir funciones miembro adicionales sería aún más feo. Normalmente no necesitarás esto.
Ejemplo:
fuente
lambda arg
ysetattr(arg, 'attr','value')
subvertir "sin asignaciones ...". Y luego está la evaluación de cortocircuito deand
yor
... es el Javascript que lo hace. Te hunde las raíces, como la hiedra en la pared. Casi espero olvidar esto por Navidad.PEP
pautas)Un par de enlaces relevantes:
Durante un tiempo, seguí el desarrollo de Reia, que inicialmente iba a tener una sintaxis basada en sangría de Python con bloques Ruby también, todo encima de Erlang. Pero, el diseñador terminó renunciando a la sensibilidad a la sangría, y esta publicación que escribió sobre esa decisión incluye una discusión sobre los problemas que encontró con la sangría + bloques de varias líneas, y una mayor apreciación que ganó por los problemas / decisiones de diseño de Guido:
http://www.unlimitednovelty.com/2009/03/indentation-sensitivity-post-mortem.html
Además, aquí hay una propuesta interesante para bloques de estilo Ruby en Python con los que me encontré, donde Guido publica una respuesta sin derribarla (aunque no estoy seguro de si ha habido un derribo posterior):
http://tav.espians.com/ruby-style-blocks-in-python.html
fuente
[Editar] Lee esta respuesta. Explica por qué la lambda multilínea no es una cosa.
En pocas palabras, no es pitónico. Del blog de Guido van Rossum:
fuente
Déjame presentarte un hack glorioso pero aterrador:
Ahora puede usar este
LET
formulario como tal:lo que da:
[0, 3, 8]
fuente
Soy culpable de practicar este truco sucio en algunos de mis proyectos, que es un poco más simple:
Espero que puedas encontrar una manera de mantenerte pitónico, pero si tienes que hacerlo es menos doloroso que usar un ejecutivo y manipular a los globales.
fuente
Permítanme tratar de abordar el problema de análisis de @balpha. Usaría paréntesis alrededor de lamda multilínea. Si no hay paréntesis, la definición lambda es codiciosa. Entonces la lambda en
devuelve una función que devuelve
(y*z, [1,2,3])
Pero
medio
donde func es la lambda multilínea que devuelve y * z. ¿Eso funciona?
fuente
map(func, [1,2,3])
y el inferior debería ser un error porque la función de mapa no tiene suficientes argumentos. También hay algunos paréntesis adicionales en el código.(Para cualquiera que todavía esté interesado en el tema).
Considere esto (incluye incluso el uso de los valores de retorno de las declaraciones en otras declaraciones dentro de la lambda "multilínea", aunque es feo hasta el punto de vomitar ;-)
fuente
state.clear()
ya que los argumentos predeterminados solo se crean una vez cuando se crea la función.Simplemente puede usar slash (
\
) si tiene varias líneas para su función lambdaEjemplo:
fuente
Estoy empezando con Python, pero viniendo de Javascript, la forma más obvia es extraer la expresión como una función ...
Ejemplo contribuido, la expresión de multiplicación
(x*2)
se extrae como función y, por lo tanto, puedo usar multilínea:https://repl.it/@datracka/python-lambda-function
Tal vez no responda exactamente a la pregunta si eso fue cómo hacer multilínea en la expresión lambda en sí , pero en caso de que alguien obtenga este hilo buscando cómo depurar la expresión (como yo), creo que ayudará
fuente
map(multiply, [1, 2, 3])
?Sobre el tema de los hacks feos, siempre puedes usar una combinación de
exec
y una función regular para definir una función multilínea como esta:Puede envolver esto en una función como:
fuente
Solo estaba jugando un poco para tratar de hacer una comprensión dict con reduce, y se me ocurrió este truco de línea:
Solo estaba tratando de hacer lo mismo que se hizo en esta comprensión de dict Javascript: https://stackoverflow.com/a/11068265
fuente
Aquí hay una implementación más interesante de lambdas multilínea. No es posible lograrlo debido a cómo Python usa las sangrías como una forma de estructurar el código.
Pero afortunadamente para nosotros, el formato de sangría se puede deshabilitar usando matrices y paréntesis.
Como algunos ya señalaron, puede escribir su código como tal:
En teoría, si se garantiza que tendrá una evaluación de izquierda a derecha, funcionaría, pero aún así perderá los valores que se pasan de una expresión a otra.
Una forma de lograr lo que es un poco más detallado es tener
Donde cada lambda recibe argumentos del anterior.
Este método le permite escribir algo que es un poco lisp / esquema como.
Entonces puedes escribir cosas como esta:
Se podría usar un método más complejo para calcular la hipotenusa
Esto devolverá una lista de números escalares para que pueda usarse para reducir múltiples valores a uno.
Tener tantos lambda ciertamente no va a ser muy eficiente, pero si estás limitado, puede ser una buena manera de hacer algo rápidamente y luego reescribirlo como una función real más adelante.
fuente
porque se supone que una función lambda tiene una línea, ya que es la forma más simple de una función,
an entrance, then return
fuente