Este código:
a = [1, 2, 3] print(*a, a.pop(0))
Python 3.8 imprime 2 3 1
(hace el pop
antes de desempacar).
Python 3.9 imprime 1 2 3 1
(aparece después de pop
).
¿Qué causó el cambio? No lo encontré en el registro de cambios .
Editar: no solo en las llamadas a funciones, sino también, por ejemplo, en una visualización de lista :
a = [1, 2, 3] b = [*a, a.pop(0)] print(b)
Imprime [2, 3, 1]
frente a [1, 2, 3, 1]
. Y las listas de expresiones dicen "Las expresiones se evalúan de izquierda a derecha" (ese es el enlace a la documentación de Python 3.8), por lo que esperaría que la expresión de desempaquetado suceda primero.
Sospecho que esto puede haber sido un accidente, aunque prefiero el nuevo comportamiento.
El nuevo comportamiento es consecuencia de un cambio en el funcionamiento del código de bytes para los argumentos *
. El cambio está en el registro de cambios en Python 3.9.0 alfa 3:
bpo-39320 : Reemplace cuatro códigos de bytes complejos para construir secuencias con tres más simples.
Se han eliminado los siguientes cuatro bytecodes:
- BUILD_LIST_UNPACK
- BUILD_TUPLE_UNPACK
- BUILD_SET_UNPACK
- BUILD_TUPLE_UNPACK_WITH_CALL
Se han añadido los siguientes tres bytecodes:
- LIST_TO_TUPLE
- LIST_EXTEND
- SET_UPDATE
En Python 3.8, el código de bytes para f(*a, a.pop())
se ve así:
1 0 LOAD_NAME 0 (f) 2 LOAD_NAME 1 (a) 4 LOAD_NAME 1 (a) 6 LOAD_METHOD 2 (pop) 8 CALL_METHOD 0 10 BUILD_TUPLE 1 12 BUILD_TUPLE_UNPACK_WITH_CALL 2 14 CALL_FUNCTION_EX 0 16 RETURN_VALUE
mientras que en 3.9, se ve así:
1 0 LOAD_NAME 0 (f) 2 BUILD_LIST 0 4 LOAD_NAME 1 (a) 6 LIST_EXTEND 1 8 LOAD_NAME 1 (a) 10 LOAD_METHOD 2 (pop) 12 CALL_METHOD 0 14 LIST_APPEND 1 16 LIST_TO_TUPLE 18 CALL_FUNCTION_EX 0 20 RETURN_VALUE
En el bytecode anterior, el código inserta a
y (a.pop(),)
en la pila, luego desempaqueta esos dos iterables en una tupla. En el nuevo código de bytes, el código inserta una lista en la pila, luego hace l.extend(a)
y l.append(a.pop())
, luego llama a tuple(l)
.
Este cambio tiene el efecto de cambiar el desempaquetado de a
antes de la llamada pop
, pero esto no parece haber sido deliberado. Mirando bpo-39320 , la intención era simplificar las instrucciones del código de bytes, no cambiar el comportamiento, y el subproceso bpo no tiene discusión sobre los cambios de comportamiento.