propias - lista de funciones de python
¿Por qué la asignación de Python no devuelve un valor? (6)
- La sintaxis de Python es mucho menos detallada que la sintaxis de C.
- Tiene reglas de alcance mucho más sofisticadas que C.
- Utilizar paréntesis en cada expresión reduce la legibilidad del código y python lo evita.
Si las asignaciones fueran expresiones, estas y muchas otras características tendrían que volver a trabajarse. Para mí es como un trato que tienes que hacer para tener un código legible y funciones útiles. Para tener
if a and (h not in b): ...
más bien que
if (a && !(h in b)) { ... }
[no estoy hablando del clásico (si a = b :) tipo de error.]
¿Por qué la asignación de Python es una declaración en lugar de una expresión? Si fuera una expresión que devuelve el valor del lado derecho en la asignación, en algunos casos habría permitido código mucho menos detallado. ¿Hay algún problema que no pueda ver?
Por ejemplo:
# lst is some sequence
# X is come class
x = X()
lst.append(x)
podría haber sido reescrito como:
lst.append(x = X())
Bueno, para ser precisos, lo anterior no funcionará porque x
trataría como un argumento de palabra clave. Pero otro par de parens (u otro símbolo para los argumentos de palabras clave) habría resuelto eso.
Creo que esto fue deliberado por parte de Guido para evitar ciertos errores clásicos. P.ej
if x = 3: print x
cuando en realidad quisiste decir
if x == 3: ...
Estoy de acuerdo en que a veces deseé que funcionara, pero también echo de menos {
y }
alrededor de un bloque de código, y eso seguro no va a cambiar.
Entrar en una discusión a gusto, o cualquier discusión percibida como tal, es generalmente una pérdida de tiempo, sin importar cuán buenos sean los argumentos.
Fuera de los principios más generales, mi razón práctica preferida para que la asignación sea una expresión es tener un equivalente legible de una declaración de caso cuando quiero hacer coincidir una cadena con varios patrones (extracción de subpatrones), hasta que tenga éxito. Tal vez alguien tiene una buena solución que yo no vi.
De todos modos ... ¿por qué no hacer felices a todos haciendo que ambos mundos estén disponibles por medio de un comentario interpretable al comienzo del archivo del módulo que establece explícitamente que las asignaciones se pueden utilizar como expresión, si el programador así lo desea?
Las personas satisfechas con la situación actual no verán ningún cambio y aún se detectarán sus errores de sintaxis de la misma manera.
Y las personas que quieran usar la asignación como expresiones simplemente tendrán que decirlo.
No veo que permitir el uso de asignaciones como expresiones en un programa existente que no lo usó (simplemente agregando el comentario sugerido arriba) cambiaría la semántica de ese programa.
Paz.
Post-sriptum: se agrega después de que se hayan publicado los primeros cinco párrafos de la sección 1 en la discusión a continuación.
No sé por qué los diseñadores de Python tomaron esa decisión. Evitar el error ciertamente común if a=b : ...
lugar de if a==b : ...
no es una justificación.
En primer lugar, podría evitarse fácilmente con otra notación para la asignación, como :=
o <-
, más apropiada ya que la asignación no es simétrica, y se usa en algunos de los primeros ancestros de Python.
En segundo lugar, el mismo problema se tolera en otro contexto. Uno puede escribir a = b=c
mientras que en realidad significa escribir a = b==c
que es bastante diferente. Y el error no es tan visible cuando b
y c
son expresiones grandes. Además, aunque probablemente se detectaría como un error de tipo si el lenguaje se escribiera estáticamente, no es así en un lenguaje de tipado dinámico como Python (esto es cierto para =
versus ==
en todos los contextos).
Esta tolerancia es tanto más sorprendente que la asignación múltiple de la forma a = b = c
no es una característica esencial del lenguaje, apenas una característica muy útil.
Todo parece ser un remanente de decisiones tempranas de diseño, algunas motivadas por similitudes con lenguajes existentes como C o Bash porque Python también es un lenguaje de scripting, pero se ha convertido en mucho más que eso. En otras palabras, parece más accidental que un diseño bien pensado. Con suerte, eso no es lo que las personas tienen en mente cuando se habla de pitonicidad.
Dicho esto, estas son restricciones sintácticas menores, aunque molestas. El lenguaje parece mucho mejor diseñado en general (con alguna restricción mental con respecto a las reglas de alcance, hasta que me decida sobre su lógica).
Un aspecto interesante de esta discusión es que la prohibición de la asignación como expresión (aunque podría resolverse mediante un cambio de notación) también se hace necesaria por la ausencia de tipado estático. Pero es de esperar que la ausencia de tipeo estático, que es una opción legítima de diseño, hace que muchos errores sean más difíciles de detectar. Esta es una observación muy general. Sin embargo, esta es la elección hecha por los diseñadores de Python. Que así sea.
Pero entonces difícilmente pueden lamentar que la confusión entre igualdad y asignación sea más difícil de atrapar. Es solo una consecuencia directa, una de las muchas consecuencias de su elección de diseño de mayor flexibilidad a expensas de la detección de errores. Entonces, la detección de errores es una excusa pobre para esta limitación en la asignación.
En cuanto al hecho de que una asignación de expresión combinaría el estilo funcional e imperativo, esto no es un problema. La mezcla ya está en todas partes en el lenguaje.
¿Existe un razonamiento escrito para Python que documente las opciones de diseño en general, y el tema tratado aquí en particular?
Hay muchos que sienten que tener asignaciones son expresiones, especialmente en lenguajes como Python, donde cualquier valor es permisible en una condición (no solo valores de algún tipo booleano), es propenso a errores. Es de suponer que Guido es / estaba entre los que se sienten así. El error clásico es:
if x = y: # oops! meant to say ==
La situación es un poco más complicada en Python que en un lenguaje como C, ya que en Python la primera asignación a una variable es también su declaración. Por ejemplo:
def f():
print x
def g():
x = h()
print x
En estas dos funciones, las líneas " print x
" hacen cosas diferentes: una se refiere a la variable global x
, y la otra se refiere a la variable local x
. La x
en g
es local debido a la asignación. Esto podría ser aún más confuso (de lo que ya es) si fuera posible enterrar la tarea dentro de una expresión / declaración más grande.
La respuesta del mundo real: no es necesaria.
La mayoría de los casos que ve esto en C se deben al hecho de que el manejo de errores se realiza de forma manual:
if((fd = open("file", O_RDONLY)) == -1)
{
// error handling
}
Del mismo modo para la forma en que se escriben muchos bucles:
while(i++ < 10)
;
Estos casos comunes se hacen de manera diferente en Python. El manejo de errores generalmente utiliza el manejo de excepciones; los bucles generalmente usan iteradores.
Los argumentos en contra no son necesariamente estremecedores, pero son sopesados contra el hecho de que simplemente no es tan importante en Python.
Puede esperar soporte para expresiones (x := y)
para ser implementadas en una versión futura de python. Recientemente, Guido aceptó una propuesta, PEP 572 en julio de 2018, para admitir expresiones de asignación en python. (También hubo propuestas anteriores para ello, como el PEP 379 retirado).
Recuerde que hasta la versión 3, print
también era una declaración en lugar de una expresión.
Nota: El enunciado x = y = z
para asignar el mismo valor a múltiples objetivos (o más bien, múltiples listas de objetivos , ya que también está permitido desempaquetar) ya se soportaba durante mucho tiempo en python, pero se implementó como una syntax especial en lugar de encadenar sucesivos sub-expresiones de asignación. (De hecho, el orden en el que se realizan las asignaciones individuales se invierte ..)