python - una - tuplas append
El orden de desempaquetado de Tuple cambia los valores asignados (4)
Prerrequisitos : 2 puntos importantes
Las listas son mutables
La parte principal en las listas es que las listas son mutables. Significa que los valores de las listas se pueden cambiar. Esta es una de las razones por las que enfrenta el problema. Consulte los documentos para obtener más información
Orden de evaluación
La otra parte es que al desempacar una tupla, la evaluación comienza de izquierda a derecha. Consulte los documentos para obtener más información
Introducción
cuando haces a,b = c,d
los valores de d
se almacenan primero. Luego comenzando desde el lado izquierdo, el valor de a
se cambia primero a c
y luego el valor de b
se cambia a d
.
La captura aquí es que si hay efectos secundarios en la ubicación de b
al cambiar el valor de a
, entonces d
se asigna a la b
posterior , que es la b
afectada por el efecto secundario de a
.
Caso de uso
Ahora llegando a tu problema
En el primer caso,
nums = [1, 2, 0]
nums[nums[0]], nums[0] = nums[0], nums[nums[0]]
nums[0]
es inicialmente 1
y nums[nums[0]]
es 2
porque evalúa nums[1]
. Por lo tanto, 1,2 ahora está almacenado en la memoria.
Ahora el desempaquetado de tuplas ocurre desde el lado izquierdo, por lo que
nums[nums[0]] = nums[1] = 1 # NO side Effect.
nums[0] = 2
por lo tanto, print nums
se imprimirá [2, 1, 0]
Sin embargo, en este caso
nums = [1, 2, 0]
nums[0], nums[nums[0]] = nums[nums[0]], nums[0]
nums[nums[0]], nums[0]
pone 2,1 en la pila como en el primer caso.
Sin embargo, en el lado izquierdo, que es nums[0], nums[nums[0]]
, el cambio de nums[0]
tiene un efecto secundario ya que se usa como índice en nums[nums[0]]
. Así
nums[0] = 2
nums[nums[0]] = nums[2] = 1 # NOTE THAT nums[0] HAS CHANGED
nums[1]
permanece sin cambios en el valor 2
. por lo tanto, print nums
se imprimirá [2, 2, 1]
Creo que los dos son idénticos.
nums = [1, 2, 0]
nums[nums[0]], nums[0] = nums[0], nums[nums[0]]
print nums # [2, 1, 0]
nums = [1, 2, 0]
nums[0], nums[nums[0]] = nums[nums[0]], nums[0]
print nums # [2, 2, 1]
Pero los resultados son diferentes.
¿Por qué los resultados son diferentes? (¿por qué es el segundo resultado?)
En el primer ejemplo, lo que ocurre es que nums [1] se establece en 1, y luego nums [0] se establece en 2, como era de esperar.
En el segundo ejemplo, nums [0] se establece en 2, y luego nums [2] se establece en 1. Esto se debe a que, en este caso, los nums del lado izquierdo [nums [0]] realmente hacen referencia a nums [2 ] cuando ocurre la asignación, porque nums [0] acababa de establecerse en 2.
Es debido a que la prioridad de asignación de Python es de izquierda a derecha. Así que en el siguiente código:
nums = [1, 2, 0]
nums[nums[0]], nums[0] = nums[0], nums[nums[0]]
Primero asignó los nums[0]
a nums[nums[0]]
significa nums[1]==1
y luego dado que las listas son objetos mutables los nums serían:
[1,1,0]
y luego nums[nums[0]]
se asignarán a nums[0]
que significa nums[0]==2
y:
nums = [2,1,0]
Y así para la segunda parte.
Tenga en cuenta que el punto importante aquí es que los objetos de la lista son mutables y cuando lo cambia en un segmento de código puede cambiarse in situ. por lo tanto, afectará al resto del código.
Python evalúa expresiones de izquierda a derecha. Tenga en cuenta que al evaluar una tarea, el lado derecho se evalúa antes que el lado izquierdo.
Puede definir una clase para seguir el proceso:
class MyList(list):
def __getitem__(self, key):
print(''get '' + str(key))
return super(MyList, self).__getitem__(key)
def __setitem__(self, key, value):
print(''set '' + str(key) + '', '' + str(value))
return super(MyList, self).__setitem__(key, value)
Para el primer método:
nums = MyList([1, 2, 0])
nums[nums[0]], nums[0] = nums[0], nums[nums[0]]
la salida es:
get 0
get 0
get 1
get 0
set 1, 1
set 0, 2
Mientras que el segundo método:
nums = MyList([1, 2, 0])
nums[0], nums[nums[0]] = nums[nums[0]], nums[0]
la salida es:
get 0
get 1
get 0
set 0, 2
get 0
set 2, 1
En ambos métodos, las primeras tres líneas están relacionadas con la generación de tuplas, mientras que las últimas tres líneas están relacionadas con las asignaciones. La tupla del lado derecho del primer método es (1, 2)
y el segundo método es (2, 1)
.
En la etapa de asignación, el primer método obtiene nums[0]
que es 1
, y establece nums[1] = 1
, luego nums[0] = 2
, segundo método asigna nums[0] = 2
, luego obtiene nums[0]
que es 2
, y finalmente establece nums[2] = 1
.