Pregunta

Ocasionalmente veo la sintaxis de corte de lista utilizada en el código de Python como esta:

newList = oldList[:]

Seguramente esto es lo mismo que:

newList = oldList

¿O me estoy perdiendo algo?

¿Fue útil?

Solución

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

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

Sin embargo, cuando haces newList = oldList [:] , se "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 el primero, pero ambos pueden modificarse sin cambiar el otro.

Otros consejos

[:] Copias superficiales la lista, haciendo una copia de la estructura de la lista que contiene referencias a los miembros originales de la lista. Esto significa que las operaciones en la copia no afectan la estructura del original. Sin embargo, si hace algo a 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 a continuación 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

Ejecutarlo en un shell de Python proporciona la siguiente transcripción. Podemos ver el lista que se hace con copias de los objetos antiguos. Uno de los objetos puede tener su estado actualizado por referencia a través de la lista anterior, y las actualizaciones pueden ser visto cuando se accede al objeto a través de la lista anterior. Finalmente, cambiando un Se puede ver que la referencia en la nueva lista no se refleja en la lista anterior, ya que 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

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 pienses que 'a = b' en Python significa 'copiar 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, una tupla o una cadena), entonces sí, el efecto es que obtienes una copia. Pero eso es porque cuando se trata de inmutables (que tal vez deberían haberse llamado solo lectura , inmutable o WORM ) usted siempre obtener una copia, por definición.

Si b es un mutable, siempre tiene que hacer algo extra para asegurarse de tener una copia verdadera . Siempre . Con las listas, es tan simple como un segmento: & nbsp; a = b [:].

La mutabilidad también es la razón de que esto:

def myfunction(mylist=[]): 
    pass

... no hace lo que crees que hace.

Si eres de un fondo C: lo que queda de '=' es un puntero, siempre. Todas las variables son punteros, siempre. Si coloca variables en una lista: & nbsp; 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 ahora apunta a lo que d apunta.

Consulte también el módulo de copia: & nbsp; http://docs.python.org/ library / copy.html

Copia superficial: (copia fragmentos de memoria de una ubicación a otra)

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 la 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']
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top