Encontré la asignación a = a[1:] = [2] en un artículo. Lo probé en python3 y python2; todo funciona, pero no entiendo cómo funciona. = aquí no es como en C; Procesos C = de derecha a izquierda. ¿Cómo procesa Python el operador = ?
Según los documentos de idioma en la asignación :
Una instrucción de asignación evalúa la lista de expresiones (recuerde que puede ser una sola expresión o una lista separada por comas, esta última genera una tupla) y asigna el único objeto resultante a cada una de las listas de destino, de izquierda a derecha.
En este caso, a = a[1:] = [2] tiene una lista de expresiones [2] y dos "listas de destino", a y a[1:] , donde a es la "lista de destino" más a la izquierda.
Puede ver cómo se comporta esto mirando el desmontaje:
>>> import dis >>> dis.dis('a = a[1:] = [2]') 1 0 LOAD_CONST 0 (2) 2 BUILD_LIST 1 4 DUP_TOP 6 STORE_NAME 0 (a) 8 LOAD_NAME 0 (a) 10 LOAD_CONST 1 (1) 12 LOAD_CONST 2 (None) 14 BUILD_SLICE 2 16 STORE_SUBSCR 18 LOAD_CONST 2 (None) 20 RETURN_VALUE (Las dos últimas líneas del desensamblado se pueden ignorar, dis está creando una función contenedora para desensamblar la cadena)
La parte importante a tener en cuenta es que cuando hace x = y = some_val , some_val se carga en la pila (en este caso por LOAD_CONST y BUILD_LIST ), luego la entrada de la pila se duplica y se asigna, de izquierda a derecha, a los objetivos dado.
Así que cuando lo hagas:
a = a[1:] = [2] hace dos referencias a una nueva list que contiene 2 , y la primera acción es STORE una de estas referencias a a . A continuación, almacena la segunda referencia a a[1:] , pero dado que la asignación del segmento muta a sí mismo, tiene que cargar a nuevamente, lo que obtiene la list recién almacenada. Afortunadamente, la list es resistente a la autoasignación de segmentos, o tendríamos problemas (sería una eternidad leyendo el valor que acaba de agregar para agregar al final hasta que nos quedemos sin memoria y fallemos); tal como está, se comporta como si se hubiera asignado una copia de [2] para reemplazar todos y cada uno de los elementos desde el índice uno en adelante.
El resultado final es equivalente a si hubieras hecho:
_ = [2] a = _ a[1:] = _ pero evita el uso del nombre _ .
Para ser claros, el desmontaje anotó:
Haz una lista [2] :
1 0 LOAD_CONST 0 (2) 2 BUILD_LIST 1 Haga una copia de la referencia a [2] :
4 DUP_TOP Realizar almacenar en a :
6 STORE_NAME 0 (a) Realizar almacenar en a a[1:] :
8 LOAD_NAME 0 (a) 10 LOAD_CONST 1 (1) 12 LOAD_CONST 2 (None) 14 BUILD_SLICE 2 16 STORE_SUBSCRLa forma en que entiendo tales asignaciones es que esto es equivalente a
temp = [2] a = temp a[1:] = temp El valor resultante de [2, 2] es consistente con esta interpretación.