2012-04-14 8 views

Respuesta

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

Crea un nuevo list en la memoria y señala el nombre a_list en ella. Es irrelevante lo que a_list señaló antes.

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

llama al método __setitem__ del objeto a_list con un slice como el índice, y un nuevo list creado en la memoria como el valor.

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

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

o la inserción de 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 "rebanadas extendidas" , donde el step no es uno, el iterable debe ser 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 sobre la asignación rebanada a a_list son:

  1. a_list ya debe apuntar a un objeto
  2. Ese objeto se modifica, en lugar de señalar a_list en un nuevo objeto
  3. Ese objeto debe ser compatible con __setitem__ con un índice de slice
  4. El objeto de la derecha debe iteración de soporte
  5. No se señala ningún nombre en el 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.
+0

Me gustó especialmente la parte editada :) – 0xc0de

+0

He leído esto en los documentos (http://docs.python.org/tutorial/introduction.html#lists). Solo el índice predeterminado era mi duda :) – 0xc0de

+1

"Para las listas, si el rango especificado por el segmento no es de la misma longitud que el iterable, la lista cambia de tamaño". Esto es cierto solo si el valor de paso del rango es 1. Para valores de paso distintos de 1, el iterable asignado debe dar la cantidad correcta de elementos. –

12

¡La diferencia es bastante grande! En

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

modificar una lista existente que fue vinculado al nombre de a_list.Por otro lado,

a_list = ['foo', 'bar'] 

asigna una nueva lista con el nombre de 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 
2

Asignando a a_list[:], a_list todavía referencia al mismo objeto de lista, con contenidos modificados. Asignando a a_list, a_list ahora referencia a un nuevo objeto de lista.

Salida 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 se puede ver, su id cambio doens't con la versión asignación rebanada.


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

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

a = ['original'] 
foo(a) 
print(a) 

Con esto, a se modifica, así, pero si a_list = ['foo', 'bar'] eran utilizado en su lugar, a mantiene su valor original.

Cuestiones relacionadas