a = [1, 2, 3] a[-1] += a.pop() Esto da como resultado [1, 6] .
a = [1, 2, 3] a[0] += a.pop() Esto da como resultado [4, 2] . ¿Qué orden de evaluación da estos dos resultados?
Primero la derecha y luego la izquierda. Y en cualquier lado, el orden de evaluación es de izquierda a derecha.
a[-1] += a.pop() es lo mismo que, a[-1] = a[-1] + a.pop()
a = [1,2,3] a[-1] = a[-1] + a.pop() # a = [1, 6]Vea cómo cambia el comportamiento cuando cambiamos el orden de las operaciones en RHS,
a = [1,2,3] a[-1] = a.pop() + a[-1] # a = [1, 5]La idea clave es que a[-1] += a.pop() es azúcar sintáctico para a[-1] = a[-1] + a.pop() . Esto es cierto porque += se aplica a un objeto inmutable (un int aquí) en lugar de un objeto mutable ( pregunta relevante aquí ).
El lado derecho (RHS) se evalúa primero. En el RHS: la sintaxis equivalente es a[-1] + a.pop() . Primero, a[-1] obtiene el último valor 3 . En segundo lugar, a.pop() return s 3 . 3 + 3 es 6 .
En el lado izquierdo (LHS), a ahora es [1,2] debido a la mutación en el lugar ya aplicada por list.pop() y, por lo tanto, el valor de a[-1] cambia de 2 a 6 .
Echemos un vistazo a la salida de dis.dis para a[-1] += a.pop() 1) :
3 15 LOAD_FAST 0 (a) # a, 18 LOAD_CONST 5 (-1) # a, -1 21 DUP_TOP_TWO # a, -1, a, -1 22 BINARY_SUBSCR # a, -1, 3 23 LOAD_FAST 0 (a) # a, -1, 3, a 26 LOAD_ATTR 0 (pop) # a, -1, 3, a.pop 29 CALL_FUNCTION 0 (0 positional, 0 keyword pair) # a, -1, 3, 3 32 INPLACE_ADD # a, -1, 6 33 ROT_THREE # 6, a, -1 34 STORE_SUBSCR # (empty)El significado de las diferentes instrucciones se enumera aquí .
Primero, LOAD_FAST y LOAD_CONST cargan a y -1 en la pila, y DUP_TOP_TWO duplica los dos, antes de BINARY_SUBSCR obtenga el valor del subíndice, lo que da como resultado a, -1, 3 en la pila. Luego carga a nuevo, y LOAD_ATTR carga la función pop , que es llamada sin argumentos por CALL_FUNCTION . La pila ahora es a, -1, 3, 3 e INPLACE_ADD agrega los dos valores principales. Finalmente, ROT_THREE gira la pila a 6, a, -1 para que coincida con el orden esperado por STORE_SUBSCR y se almacena el valor.
Entonces, en resumen, el valor actual de a[-1] se evalúa antes de llamar a a.pop() y el resultado de la suma se almacena nuevamente en el nuevo a[-1] , independientemente de su valor actual.
1) Este es el desensamblado de Python 3, ligeramente comprimido para que quepa mejor en la página, con una columna agregada que muestra la pila después de # ... ; para Python 2 se ve un poco diferente, pero similar.