variable library dict deepcopy python list shallow-copy

library - Sintaxis de la sección de la lista de Python utilizada sin una razón obvia



python copy string (5)

Ocasionalmente veo la sintaxis del sector de la lista utilizada en el código de Python como este:

newList = oldList[:]

Sin duda, esto es lo mismo que:

newList = oldList

¿O me estoy perdiendo algo?


Como dijo NXC, los nombres de las variables de Python apuntan a un objeto, y no a un lugar específico en la memoria.

newList = oldList crearía dos variables diferentes que apuntan al mismo objeto, por lo tanto, al cambiar oldList también cambiaría newList .

Sin embargo, cuando hace newList = oldList[:] , "corta" la lista y crea una nueva lista. Los valores predeterminados para [:] son 0 y el final de la lista, por lo que copia todo. Por lo tanto, crea una nueva lista con todos los datos contenidos en la primera, pero ambos pueden modificarse sin cambiar la otra.


Como ya se ha respondido, simplemente agregaré una demostración simple:

>>> a = [1, 2, 3, 4] >>> b = a >>> c = a[:] >>> b[2] = 10 >>> c[3] = 20 >>> a [1, 2, 10, 4] >>> b [1, 2, 10, 4] >>> c [1, 2, 3, 20]


Nunca piense que ''a = b'' en Python significa ''copia b a a''. Si hay variables en ambos lados, realmente no puedes saber eso. En cambio, piense en ello como ''dar a b el nombre adicional a''.

Si b es un objeto inmutable (como un número, tupla o una cadena), entonces sí, el efecto es que obtienes una copia. Pero eso se debe a que cuando trabajas con elementos inmutables (que tal vez deberían llamarse de solo lectura , inmutables o WORM ) siempre obtienes una copia, por definición.

Si b es un mutable, siempre debe hacer algo adicional para asegurarse de tener una copia verdadera . Siempre . Con las listas, es tan simple como un segmento: a = b [:].

La mudabilidad es también la razón por la cual esto:

def myfunction(mylist=[]): pass

... no hace exactamente lo que crees que hace.

Si eres de un C-fondo: lo que queda de ''='' es un puntero, siempre. Todas las variables son punteros, siempre. Si coloca variables en una lista: a = [b, c], ha puesto punteros a los valores apuntados por byc en una lista apuntada por a. Si luego establece un [0] = d, el puntero en la posición 0 apunta ahora a lo que d apunta.

Ver también el módulo de copia: http://docs.python.org/library/copy.html


[:] Shallow copia la lista, haciendo una copia de la estructura de la lista que contiene referencias a los miembros de la lista original. Esto significa que las operaciones en la copia no afectan la estructura del original. Sin embargo, si haces algo con los miembros de la lista, ambas listas aún se refieren a ellos, por lo que las actualizaciones se mostrarán si se accede a los miembros a través del original.

Una copia profunda también haría copias de todos los miembros de la lista.

El fragmento de código siguiente muestra una copia superficial en acción.

# ================================================================ # === ShallowCopy.py ============================================= # ================================================================ # class Foo: def __init__(self, data): self._data = data aa = Foo (''aaa'') bb = Foo (''bbb'') # The initial list has two elements containing ''aaa'' and ''bbb'' OldList = [aa,bb] print OldList[0]._data # The shallow copy makes a new list pointing to the old elements NewList = OldList[:] print NewList[0]._data # Updating one of the elements through the new list sees the # change reflected when you access that element through the # old list. NewList[0]._data = ''xxx'' print OldList[0]._data # Updating the new list to point to something new is not reflected # in the old list. NewList[0] = Foo (''ccc'') print NewList[0]._data print OldList[0]._data

Al ejecutarlo en un shell de python se obtiene la siguiente transcripción. Podemos ver la lista hecha con copias de los objetos viejos. Uno de los objetos puede tener su estado actualizado por referencia a través de la lista anterior, y las actualizaciones se pueden ver cuando se accede al objeto a través de la lista anterior. Finalmente, se puede ver que al cambiar una referencia en la nueva lista no se refleja en la lista anterior, ya que la nueva lista ahora se refiere a un objeto diferente.

>>> # ================================================================ ... # === ShallowCopy.py ============================================= ... # ================================================================ ... # ... class Foo: ... def __init__(self, data): ... self._data = data ... >>> aa = Foo (''aaa'') >>> bb = Foo (''bbb'') >>> >>> # The initial list has two elements containing ''aaa'' and ''bbb'' ... OldList = [aa,bb] >>> print OldList[0]._data aaa >>> >>> # The shallow copy makes a new list pointing to the old elements ... NewList = OldList[:] >>> print NewList[0]._data aaa >>> >>> # Updating one of the elements through the new list sees the ... # change reflected when you access that element through the ... # old list. ... NewList[0]._data = ''xxx'' >>> print OldList[0]._data xxx >>> >>> # Updating the new list to point to something new is not reflected ... # in the old list. ... NewList[0] = Foo (''ccc'') >>> print NewList[0]._data ccc >>> print OldList[0]._data xxx


Copia superficial: (copia trozos de memoria de un lugar a otro)

a = [''one'',''two'',''three''] b = a[:] b[1] = 2 print id(a), a #Output: 1077248300 [''one'', ''two'', ''three''] print id(b), b #Output: 1077248908 [''one'', 2, ''three'']

Copia profunda: (copia referencia del objeto)

a = [''one'',''two'',''three''] b = a b[1] = 2 print id(a), a #Output: 1077248300 [''one'', 2, ''three''] print id(b), b #Output: 1077248300 [''one'', 2, ''three'']