slicing operator español python list variable-assignment slice

python - operator - ¿Cuál es la diferencia entre la asignación de división que divide toda la lista y la asignación directa?



slice operator in python (3)

Veo en muchos lugares el uso de la asignación de sectores para list s. Puedo entender su uso cuando se usa con índices (no predeterminados), pero no puedo entender su uso como:

a_list[:] = [''foo'', ''bar'']

¿Cómo es eso diferente de

a_list = [''foo'', ''bar'']

?


¡La diferencia es bastante grande! En

a_list[:] = [''foo'', ''bar'']

Usted modifica una lista existente que estaba vinculada al nombre a_list . Por otra parte,

a_list = [''foo'', ''bar'']

asigna una nueva lista al nombre a_list .

Tal vez esto ayude:

a = a_list = [''foo'', ''bar''] # another name for the same list a_list = [''x'', ''y''] # reassigns the name a_list print a # still the original list a = a_list = [''foo'', ''bar''] a_list[:] = [''x'', ''y''] # changes the existing list bound to a print a # a changed too since you changed the object


a_list = [''foo'', ''bar'']

Crea una nueva list en la memoria y señala el nombre a_list en ella. Es irrelevante a lo que a_list apuntaba antes.

a_list[:] = [''foo'', ''bar'']

Llama al método a_list objeto a_list con un sector como el índice, y una nueva list creada en la memoria como el valor.

__setitem__ evalúa el sector para descubrir qué índices representa y lo llama al valor que se pasó. Luego itera sobre el objeto, estableciendo cada índice dentro del rango especificado por el sector al siguiente valor del objeto. Para las list , si el rango especificado por el sector no es de la misma longitud que el slice iterativo, la list cambia de tamaño. Esto le permite hacer una serie de cosas interesantes, como eliminar secciones de una lista:

a_list[:] = [] # deletes all the items in the list, equivalent to ''del a_list[:]''

o insertando nuevos valores en el medio de una lista:

a_list[1:1] = [1, 2, 3] # inserts the new values at index 1 in the list

Sin embargo, con "sectores extendidos", donde el step no es uno, el iterable debe tener la longitud correcta:

>>> lst = [1, 2, 3] >>> lst[::2] = [] Traceback (most recent call last): File "<interactive input>", line 1, in <module> ValueError: attempt to assign sequence of size 0 to extended slice of size 2

Las principales cosas que son diferentes acerca de la asignación de a_list a una a_list son:

  1. a_list ya debe apuntar a un objeto
  2. Ese objeto se modifica, en lugar de apuntar a_list a un nuevo objeto
  3. Ese objeto debe ser compatible con __setitem__ con un índice de sector
  4. El objeto de la derecha debe ser compatible con la iteración
  5. Ningún nombre apunta al objeto a la derecha. Si no hay otras referencias a la misma (como cuando es literal como en su ejemplo), será referencia contada fuera de existencia después de que se complete la iteración.

Al asignar a a_list[:] , a_list sigue a_list referencia al mismo objeto de la lista, con los contenidos modificados. Al asignar a a_list , a_list ahora hace referencia a un nuevo objeto de lista.

Mira su id :

>>> a_list = [] >>> id(a_list) 32092040 >>> a_list[:] = [''foo'', ''bar''] >>> id(a_list) 32092040 >>> a_list = [''foo'', ''bar''] >>> id(a_list) 35465096

Como puede ver, su id no cambia con la versión de asignación de división.

La diferencia entre los dos podría resultar en un resultado bastante diferente, por ejemplo, cuando la lista es un parámetro de función:

def foo(a_list): a_list[:] = [''foo'', ''bar''] a = [''original''] foo(a) print(a)

Con esto, a se modifica, pero si a_list = [''foo'', ''bar''] se usa en su lugar, a permanece su valor original.