python - tuplas - obtener el valor de una tupla
Python tuple desempacando en la declaraciĆ³n de devoluciĆ³n (1)
Sospecho que esto es un accidente, basado en los comentarios de este commit para Python 3.2.
Esa confirmación permitió que la expresión de asignación tomara una producción
testlist_star_expr
(lo que permite el desempaquetado no sintetizado), pero dejó la instrucción return tomando una producción de lista de
testlist
.
Sospecho que el commit simplemente se perdió esto (y posiblemente otras ubicaciones, pero me estoy centrando en la producción
return_stmt
por ahora).
Seguí adelante y modifiqué el archivo Python Grammar / Grammar para permitir esto.
Todas las pruebas continúan pasando, incluidas las del archivo
test_grammar.py
(pero esto no parece terriblemente exhaustivo).
Si tienes curiosidad, este es el cambio que hice . Siéntase libre de clonar o descargar mi tenedor .
ACTUALIZACIÓN: He enviado un problema de bpo y una solicitud de extracción para el desempaquetado de devolución (y rendimiento).
El lenguaje Python (especialmente 3.x) permite el desempaque muy general de iterables, un ejemplo simple de lo cual es
a, *rest = 1, 2, 3
Con los años, este desempaque se ha generalizado gradualmente (ver, por ejemplo, PEP 3132 y PEP 448 ), lo que permite su uso en más y más circunstancias. Como tal, me sorprendió descubrir que lo siguiente es una sintaxis no válida en Python 3.6 (y lo sigue siendo en Python 3.7):
def f():
rest = [2, 3]
return 1, *rest # Invalid
Puedo hacer que funcione encapsulando la tupla devuelta entre paréntesis de esta manera:
def f():
rest = [2, 3]
return (1, *rest) # Valid
El hecho de que use esto en una declaración de
return
parece ser importante, ya que
t = 1, *rest
es de hecho legal y resulta en lo mismo con y sin paréntesis.
¿Los desarrolladores de Python simplemente han olvidado este caso, o hay alguna razón por la cual este caso es una sintaxis no válida?
Por que me importa
Esto rompe un contrato importante que pensé que tenía con el lenguaje Python. Considere la siguiente solución (también válida):
def f():
rest = [2, 3]
t = 1, *rest
return t
Normalmente, cuando tengo un código como este, considero que
t
es un nombre temporal, del que debería poder deshacerme simplemente reemplazando
t
en la línea inferior con su definición.
Sin embargo, en este caso, esto conduce al código no válido
def f():
rest = [2, 3]
return 1, *rest
Por supuesto, no es gran cosa tener que colocar paréntesis alrededor del valor de retorno, pero generalmente solo se necesitan paréntesis adicionales para distinguir entre varios resultados posibles (agrupación). Aquí este no es el caso, ya que omitir los paréntesis no produce ningún otro comportamiento no deseado, sino más bien ningún comportamiento.