¿Cómo clonar o copiar una lista?

¿Cuáles son las opciones para clonar o copiar una lista en Python?

Al usar new_list = my_list , cualquier modificación a new_list cambia my_list cada vez. ¿Por qué es esto?

Con new_list = my_list , en realidad no tienes dos listas. La asignación simplemente copia la referencia a la lista, no la lista real, por lo que tanto new_list y my_list refieren a la misma lista después de la asignación.

Para copiar la lista, tienes varias posibilidades:

  • Puede usar el método list.copy() (disponible desde Python 3.3):

     new_list = old_list.copy() 
  • Puedes cortarlo:

     new_list = old_list[:] 

    La opinión de Alex Martelli (al menos en 2007 ) acerca de esto es que es una syntax extraña y que no tiene sentido usarla nunca . 😉 (En su opinión, el siguiente es más legible).

  • Puedes usar la función integrada en la list() :

     new_list = list(old_list) 
  • Puedes usar copy.copy() genérico copy.copy() :

     import copy new_list = copy.copy(old_list) 

    Esto es un poco más lento que list() porque primero tiene que averiguar el tipo de datos de old_list .

  • Si la lista contiene objetos y también desea copiarlos, use copy.deepcopy() genérico copy.deepcopy() :

     import copy new_list = copy.deepcopy(old_list) 

    Obviamente, el método más lento y que más memoria necesita, pero a veces inevitable.

Ejemplo:

 import copy class Foo(object): def __init__(self, val): self.val = val def __repr__(self): return str(self.val) foo = Foo(1) a = ['foo', foo] b = a.copy() c = a[:] d = list(a) e = copy.copy(a) f = copy.deepcopy(a) # edit orignal list and instance a.append('baz') foo.val = 5 print('original: %r\n list.copy(): %r\n slice: %r\n list(): %r\n copy: %r\n deepcopy: %r' % (a, b, c, d, e, f)) 

Resultado:

 original: ['foo', 5, 'baz'] list.copy(): ['foo', 5] slice: ['foo', 5] list(): ['foo', 5] copy: ['foo', 5] deepcopy: ['foo', 1] 

Félix ya proporcionó una excelente respuesta, pero pensé que haría una comparación de velocidad de los diversos métodos:

  1. 10.59 sec (105.9us / itn) – copy.deepcopy(old_list)
  2. 10.16 sec (101.6us / itn) – Método de copia Copy() puro de python que copia clases con copia profunda
  3. 1.488 sec (14.88us / itn) – Método Copy() python puro que no copia clases (solo dicts / listas / tuplas)
  4. 0.325 sec (3.25us / itn) – for item in old_list: new_list.append(item)
  5. 0.217 sec (2.17us / itn) – [i for i in old_list] (una lista de comprensión )
  6. 0.186 seg (1.86us / itn) – copy.copy(old_list)
  7. 0.075 sec (0.75us / itn) – list(old_list)
  8. 0.053 sec (0.53us / itn) – new_list = []; new_list.extend(old_list) new_list = []; new_list.extend(old_list)
  9. 0.039 sec (0.39us / itn) – old_list[:] ( corte de lista )

Así que lo más rápido es cortar la lista. Pero tenga en cuenta que copy.copy() , list[:] y list(list) , a diferencia de copy.deepcopy() y la versión de python no copian ninguna lista, diccionario o instancia de clase en la lista, así que si los originales cambian , también cambiarán en la lista copiada y viceversa.

(Aquí está el guión si alguien está interesado o quiere plantear algún problema 🙂

 from copy import deepcopy class old_class: def __init__(self): self.blah = 'blah' class new_class(object): def __init__(self): self.blah = 'blah' dignore = {str: None, unicode: None, int: None, type(None): None} def Copy(obj, use_deepcopy=True): t = type(obj) if t in (list, tuple): if t == tuple: # Convert to a list if a tuple to # allow assigning to when copying is_tuple = True obj = list(obj) else: # Otherwise just do a quick slice copy obj = obj[:] is_tuple = False # Copy each item recursively for x in xrange(len(obj)): if type(obj[x]) in dignore: continue obj[x] = Copy(obj[x], use_deepcopy) if is_tuple: # Convert back into a tuple again obj = tuple(obj) elif t == dict: # Use the fast shallow dict copy() method and copy any # values which aren't immutable (like lists, dicts etc) obj = obj.copy() for k in obj: if type(obj[k]) in dignore: continue obj[k] = Copy(obj[k], use_deepcopy) elif t in dignore: # Numeric or string/unicode? # It's immutable, so ignore it! pass elif use_deepcopy: obj = deepcopy(obj) return obj if __name__ == '__main__': import copy from time import time num_times = 100000 L = [None, 'blah', 1, 543.4532, ['foo'], ('bar',), {'blah': 'blah'}, old_class(), new_class()] t = time() for i in xrange(num_times): Copy(L) print 'Custom Copy:', time()-t t = time() for i in xrange(num_times): Copy(L, use_deepcopy=False) print 'Custom Copy Only Copying Lists/Tuples/Dicts (no classes):', time()-t t = time() for i in xrange(num_times): copy.copy(L) print 'copy.copy:', time()-t t = time() for i in xrange(num_times): copy.deepcopy(L) print 'copy.deepcopy:', time()-t t = time() for i in xrange(num_times): L[:] print 'list slicing [:]:', time()-t t = time() for i in xrange(num_times): list(L) print 'list(L):', time()-t t = time() for i in xrange(num_times): [i for i in L] print 'list expression(L):', time()-t t = time() for i in xrange(num_times): a = [] a.extend(L) print 'list extend:', time()-t t = time() for i in xrange(num_times): a = [] for y in L: a.append(y) print 'list append:', time()-t t = time() for i in xrange(num_times): a = [] a.extend(i for i in L) print 'generator expression extend:', time()-t 

EDITAR : Agregó clases de estilo antiguo, estilo antiguo y dictados a los puntos de referencia, hizo que la versión de Python fuera mucho más rápida y agregó algunos métodos más, incluyendo expresiones de lista y extend() .

Me han dicho que Python 3.3+ agrega el método list.copy() , que debería ser tan rápido como cortar:

newlist = old_list.copy()

¿Cuáles son las opciones para clonar o copiar una lista en Python?

En Python 3, se puede hacer una copia superficial con:

 a_copy = a_list.copy() 

En Python 2 y 3, puede obtener una copia superficial con una porción completa del original:

 a_copy = a_list[:] 

Explicación

Hay dos formas semánticas de copiar una lista. Una copia superficial crea una nueva lista de los mismos objetos, una copia profunda crea una nueva lista que contiene nuevos objetos equivalentes.

Copia de la lista superficial

Una copia superficial solo copia la lista, que es un contenedor de referencias a los objetos de la lista. Si los objetos contenidos en sí mismos son mutables y uno se cambia, el cambio se reflejará en ambas listas.

Hay diferentes formas de hacer esto en Python 2 y 3. Las formas de Python 2 también funcionarán en Python 3.

Python 2

En Python 2, la forma idiomática de hacer una copia superficial de una lista es con una porción completa del original:

 a_copy = a_list[:] 

También puede lograr lo mismo pasando la lista a través del constructor de listas,

 a_copy = list(a_list) 

Pero usar el constructor es menos eficiente:

 >>> timeit >>> l = range(20) >>> min(timeit.repeat(lambda: l[:])) 0.30504298210144043 >>> min(timeit.repeat(lambda: list(l))) 0.40698814392089844 

Python 3

En Python 3, las listas obtienen el método list.copy :

 a_copy = a_list.copy() 

En Python 3.5:

 >>> import timeit >>> l = list(range(20)) >>> min(timeit.repeat(lambda: l[:])) 0.38448613602668047 >>> min(timeit.repeat(lambda: list(l))) 0.6309100328944623 >>> min(timeit.repeat(lambda: l.copy())) 0.38122922903858125 

Hacer otro puntero no hace una copia.

Al usar new_list = my_list, se modifica new_list cada vez que cambia my_list. ¿Por qué es esto?

my_list es solo un nombre que apunta a la lista real en la memoria. Cuando dices new_list = my_list no estás haciendo una copia, solo estás agregando otro nombre que apunta a esa lista original en la memoria. Podemos tener problemas similares cuando hacemos copias de listas.

 >>> l = [[], [], []] >>> l_copy = l[:] >>> l_copy [[], [], []] >>> l_copy[0].append('foo') >>> l_copy [['foo'], [], []] >>> l [['foo'], [], []] 

La lista es solo una serie de punteros a los contenidos, por lo que una copia superficial simplemente copia los punteros, de modo que tiene dos listas diferentes, pero tienen el mismo contenido. Para hacer copias de los contenidos, necesita una copia profunda.

Copias profundas

Para hacer una copia en profundidad de una lista, en Python 2 o 3, use deepcopy en el módulo de copy :

 import copy a_deep_copy = copy.deepcopy(a_list) 

Para demostrar cómo esto nos permite hacer nuevas sub-listas:

 >>> import copy >>> l [['foo'], [], []] >>> l_deep_copy = copy.deepcopy(l) >>> l_deep_copy[0].pop() 'foo' >>> l_deep_copy [[], [], []] >>> l [['foo'], [], []] 

Y así vemos que la lista copiada en profundidad es una lista completamente diferente de la original. Puedes rodar tu propia función, pero no lo hagas. Es probable que cree errores que de otro modo no tendría utilizando la función de copia en profundidad de la biblioteca estándar.

No use eval

Puede ver esto usado como una forma de copia en profundidad, pero no lo haga:

 problematic_deep_copy = eval(repr(a_list)) 
  1. Es peligroso, especialmente si está evaluando algo de una fuente en la que no confía.
  2. No es confiable, si un subelemento que está copiando no tiene una representación que se pueda evaluar para reproducir un elemento equivalente.
  3. También es menos performante.

En 64 bit Python 2.7:

 >>> import timeit >>> import copy >>> l = range(10) >>> min(timeit.repeat(lambda: copy.deepcopy(l))) 27.55826997756958 >>> min(timeit.repeat(lambda: eval(repr(l)))) 29.04534101486206 

en 64 bit Python 3.5:

 >>> import timeit >>> import copy >>> l = list(range(10)) >>> min(timeit.repeat(lambda: copy.deepcopy(l))) 16.84255409205798 >>> min(timeit.repeat(lambda: eval(repr(l)))) 34.813894678023644 

Ya hay muchas respuestas que te dicen cómo hacer una copia correcta, pero ninguna de ellas dice por qué falló tu “copia” original.

Python no almacena valores en variables; enlaza nombres a objetos. Su asignación original tomó el objeto al que hace referencia my_list y también lo vinculó a new_list . my_list nombre que use, todavía hay una sola lista, por lo que los cambios realizados al referirse a ella como my_list persistirán al referirse a ella como new_list . Cada una de las otras respuestas a esta pregunta le brinda diferentes formas de crear un nuevo objeto para vincularlo a new_list .

Cada elemento de una lista actúa como un nombre, en el sentido de que cada elemento se enlaza de forma no exclusiva a un objeto. Una copia superficial crea una nueva lista cuyos elementos se unen a los mismos objetos que antes.

 new_list = list(my_list) # or my_list[:], but I prefer this syntax # is simply a shorter way of: new_list = [element for element in my_list] 

Para llevar su copia de la lista un paso más allá, copie cada objeto al que hace referencia su lista y vincule esas copias de elementos a una nueva lista.

 import copy # each element must have __copy__ defined for this... new_list = [copy.copy(element) for element in my_list] 

Esto aún no es una copia profunda, porque cada elemento de una lista puede referirse a otros objetos, al igual que la lista está vinculada a sus elementos. Para copiar recursivamente cada elemento de la lista, y luego cada otro objeto al que hace referencia cada elemento, y así sucesivamente: realice una copia en profundidad.

 import copy # each element must have __deepcopy__ defined for this... new_list = copy.deepcopy(my_list) 

Consulte la documentación para obtener más información sobre los casos de esquina en la copia.

new_list = list(old_list)

Usa la thing[:]

 >>> a = [1,2] >>> b = a[:] >>> a += [3] >>> a [1, 2, 3] >>> b [1, 2] >>> 

El idioma de Python para hacer esto es newList = oldList[:]

A diferencia de otros idiomas que tienen variables y valores , Python tiene nombre y objeto .

Esta statement:

 a = [1,2,3] 

significa dar a la lista (objeto) un nombre a , y, esto:

 b = a 

simplemente le da al mismo objeto a nuevo nombre b , de modo que cada vez que haga algo con a , el objeto cambia y, por lo tanto, b cambia.

La única forma de hacer una copia real de una es crear un nuevo objeto como han dicho otras respuestas.

Puedes ver más sobre esto aquí .

Todos los demás colaboradores dieron excelentes respuestas, que funcionan cuando tiene una lista de una sola dimensión (nivelada); sin embargo, de los métodos mencionados hasta ahora, solo copy.deepcopy() trabaja para clonar / copiar una lista y no hacer que apunte al Objetos de list anidadas cuando trabaja con listas anidadas multidimensionales (lista de listas). Si bien Felix Kling se refiere a esto en su respuesta, hay un poco más sobre el problema y posiblemente una solución alternativa que deepcopy integradas que podrían ser una alternativa más rápida a la deepcopy .

Mientras new_list = old_list[:] , copy.copy(old_list)' y para Py3k old_list.copy() funcionan para listas de un solo nivel, vuelven a señalar los objetos de list nesteds dentro de old_list y new_list , y cambian a uno De la list objetos se perpetúan en el otro.

Edit: Nueva información traída a la luz

Como fue señalado por Aaron Hall y PM 2Ring, el uso de eval() no solo es una mala idea, sino que es mucho más lento que copy.deepcopy() .

Esto significa que para las listas multidimensionales, la única opción es copy.deepcopy() . Dicho esto, realmente no es una opción, ya que el rendimiento va hacia el sur cuando intentas usarlo en una matriz multidimensional de tamaño moderado. Intenté timeit uso de una matriz 42×42, que no es inaudita ni tan grande para las aplicaciones de bioinformática, y renuncié a esperar una respuesta y simplemente comencé a escribir mi edición en esta publicación.

Parecería que la única opción real entonces es inicializar múltiples listas y trabajar en ellas de manera independiente. Si alguien tiene alguna otra sugerencia, sobre cómo manejar la copia multidimensional de listas, se agradecería.

Como han dicho otros, puede haber problemas de rendimiento significativos utilizando el módulo de copy y copy.deepcopy para listas multidimensionales . Tratando de encontrar una forma diferente de copiar la lista multidimensional sin usar deepcopy (estaba trabajando en un problema para un curso que solo permite 5 segundos para que se ejecute todo el algoritmo para recibir crédito), se me ocurrió una manera de usar funciones incorporadas para hacer una copia de la lista anidada sin tener que apuntar entre sí o en la list objetos nesteds dentro de ellas. Utilicé eval() y repr() en la asignación para hacer la copia de la lista antigua en la lista nueva sin crear un enlace a la lista antigua. Toma la forma de:

 new_list = eval(repr(old_list)) 

Básicamente, lo que hace es hacer una representación de old_list como una cadena y luego evalúa la cadena como si fuera el objeto que representa la cadena. Al hacer esto, no se crea un enlace al objeto de list original. Se crea un nuevo objeto de list y cada variable apunta a su propio objeto independiente. Aquí hay un ejemplo usando una lista anidada bidimensional.

 old_list = [[0 for j in range(y)] for i in range(x)] # initialize (x,y) nested list # assign a copy of old_list to new list without them pointing to the same list object new_list = eval(repr(old_list)) # make a change to new_list for j in range(y): for i in range(x): new_list[i][j] += 1 

Si luego verifica el contenido de cada lista, por ejemplo, una lista de 4 por 3, Python devolverá

 >>> new_list [[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1]] >>> old_list [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]] 

Si bien esto probablemente no es la forma canónica o sintácticamente correcta de hacerlo, parece funcionar bien. No he probado el rendimiento, pero voy a suponer que eval() y rep() tendrán menos sobrecarga que ejecutar que deepcopy .

Empecemos por el principio y exploremos un poco más profundo:

Supongamos que tienes dos listas:

 list_1=['01','98'] list_2=[['01','98']] 

Y tenemos que copiar ambas listas, ahora a partir de la primera lista:

Así que primero probemos por el método general de copia:

 copy=list_1 

Ahora, si está pensando en copiar, copie la lista_1, entonces puede estar equivocado, revisémoslo:

 The id() function shows us that both variables point to the same list object, ie they share this object. 
 print(id(copy)) print(id(list_1)) 

salida:

 4329485320 4329485320 

Sorprendido? Ok, vamos a explorarlo:

Entonces, como sabemos, Python no almacena nada en una variable, las Variables solo hacen referencia al objeto y al objeto almacenan el valor. Aquí el objeto es una list pero creamos dos referencias a ese mismo objeto con dos nombres de variables diferentes. Entonces ambas variables apuntan al mismo objeto:

así que cuando haces copy=list_1 lo que realmente está haciendo:

introduzca la descripción de la imagen aquí

Aquí en la lista de imágenes y copia hay dos nombres de variables, pero el objeto es el mismo para ambas variables, que es la list

Por lo tanto, si intenta modificar la lista copiada, también modificará la lista original, ya que la lista es solo una, la modificará desde la lista copiada o desde la lista original:

 copy[0]="modify" print(copy) print(list_1) 

salida:

 ['modify', '98'] ['modify', '98'] 

Así se modificó la lista original:

Entonces, cual es la solución?

Solución:

Ahora vamos a pasar a un segundo método python para copiar la lista:

 copy_1=list_1[:] 

Ahora, este método arregla lo que enfrentábamos en el primer problema, comprobémoslo:

 print(id(copy_1)) print(id(list_1)) 4338792136 4338791432 

Entonces, como podemos ver que nuestras dos listas tienen una identificación diferente y significa que ambas variables apuntan a diferentes objetos, entonces lo que realmente está sucediendo aquí es:

introduzca la descripción de la imagen aquí

Ahora intentemos modificar la lista y veamos si aún enfrentamos el problema anterior:

 copy_1[0]="modify" print(list_1) print(copy_1) 

Salida:

 ['01', '98'] ['modify', '98'] 

Entonces, como pueden ver, no está modificando la lista original, solo modificó la lista copiada, así que estamos de acuerdo con ella.

Así que ahora creo que hemos terminado? espera, tenemos que copiar la segunda lista anidada también, así que vamos a probar de forma pythonic:

 copy_2=list_2[:] 

Así que list_2 debería hacer referencia a otro objeto que es copia de list_2. Verifiquemos:

 print(id((list_2)),id(copy_2)) 

obtenemos la salida:

 4330403592 4330403528 

Ahora podemos suponer que ambas listas apuntan a un objeto diferente, así que ahora intentemos modificarlo y veamos que está dando lo que queremos:

Así que cuando intentamos:

 copy_2[0][1]="modify" print(list_2,copy_2) 

Nos da salida:

 [['01', 'modify']] [['01', 'modify']] 

Ahora, esto es un poco confuso, usamos la forma pythonica y aún así, estamos enfrentando el mismo problema.

entendámoslo:

Entonces cuando hacemos:

 copy_2=list_2[:] 

en realidad estamos copiando solo la lista externa, no la lista anidada, por lo que la lista anidada es el mismo objeto para ambas listas, revisemos:

 print(id(copy_2[0])) print(id(list_2[0])) 

salida:

 4329485832 4329485832 

Así que en realidad cuando hacemos copy_2=list_2[:] esto es lo que sucede:

introduzca la descripción de la imagen aquí

Crea la copia de la lista pero solo la copia de la lista externa, no la copia de la lista anidada, la lista anidada es la misma para ambas variables, por lo que si intenta modificar la lista anidada, también modificará la lista original porque la lista de objetos nesteds es igual para ambas. lista anidada

¿Entonces, cuál es la solución?

La solución es deep copy

 from copy import deepcopy deep=deepcopy(list_2) 

Así que ahora vamos a comprobarlo:

 print(id((list_2)),id(deep)) 

salida:

 4322146056 4322148040 

ambas identificaciones son diferentes, ahora verifiquemos la identificación de lista anidada

 print(id(deep[0])) print(id(list_2[0])) 

salida:

 4322145992 4322145800 

Como puede ver, ambas identificaciones son diferentes, por lo que podemos suponer que ambas listas anidadas apuntan a un objeto diferente ahora.

Entonces, cuando haces deep=deepcopy(list_2) lo que realmente sucede:

introduzca la descripción de la imagen aquí

Así que ambas listas anidadas apuntan a un objeto diferente y ahora tienen una copia por separado de la lista anidada.

Ahora intentemos modificar la lista anidada y veamos si resolvió el problema anterior o no:

así que si lo hacemos:

 deep[0][1]="modify" print(list_2,deep) 

salida:

 [['01', '98']] [['01', 'modify']] 

Como puede ver, no modificó la lista anidada original, solo modificó la lista copiada.

Si le gusta mi respuesta detallada, hágamelo saber mediante la votación, si tiene alguna duda sobre esta respuesta, comente abajo 🙂

Python 3.6.0 Tiempos

Aquí están los resultados de tiempo usando Python 3.6.0. Tenga en cuenta que estos tiempos son relativos entre sí, no absolutos.

Me limité a hacer solo copias poco profundas, y también agregué algunos métodos nuevos que no eran posibles en Python2, como list.copy() (el equivalente de corte de Python3) y desempaquetado de listas ( *new_list, = list ):

 METHOD TIME TAKEN b = a[:] 6.468942025996512 #Python2 winner b = a.copy() 6.986593422974693 #Python3 "slice equivalent" b = []; b.extend(a) 7.309216841997113 b = a[0:len(a)] 10.916740721993847 *b, = a 11.046738261007704 b = list(a) 11.761539687984623 b = [i for i in a] 24.66165203397395 b = copy.copy(a) 30.853400873980718 b = [] for item in a: b.append(item) 48.19176080400939 

Podemos ver que el antiguo ganador aún está en la cima, pero no en gran medida, considerando la mayor legibilidad del enfoque de list.copy() copia de list.copy() .

Tenga en cuenta que estos métodos no generan resultados equivalentes para ninguna entrada que no sean listas. Todos funcionan para objetos que se pueden cortar, algunos funcionan para cualquier iterable, pero solo copy.copy() funciona para cualquier objeto Python.


Aquí está el código de prueba para las partes interesadas ( Plantilla de aquí ):

 import timeit COUNT = 50000000 print("Array duplicating. Tests run", COUNT, "times") setup = 'a = [0,1,2,3,4,5,6,7,8,9]; import copy' print("b = list(a)\t\t", timeit.timeit(stmt='b = list(a)', setup=setup, number=COUNT)) print("b = copy.copy(a)\t\t", timeit.timeit(stmt='b = copy.copy(a)', setup=setup, number=COUNT)) print("b = a.copy()\t\t", timeit.timeit(stmt='b = a.copy()', setup=setup, number=COUNT)) print("b = a[:]\t\t", timeit.timeit(stmt='b = a[:]', setup=setup, number=COUNT)) print("b = a[0:len(a)]\t", timeit.timeit(stmt='b = a[0:len(a)]', setup=setup, number=COUNT)) print("*b, = a\t", timeit.timeit(stmt='*b, = a', setup=setup, number=COUNT)) print("b = []; b.extend(a)\t", timeit.timeit(stmt='b = []; b.extend(a)', setup=setup, number=COUNT)) print("b = []\nfor item in a: b.append(item)\t", timeit.timeit(stmt='b = []\nfor item in a: b.append(item)', setup=setup, number=COUNT)) print("b = [i for i in a]\t", timeit.timeit(stmt='b = [i for i in a]', setup=setup, number=COUNT)) 

Me sorprende que esto no haya sido mencionado aún, así que para completar …

Puede realizar el desempaquetado de la lista con el “operador splat”: * , que también copiará los elementos de su lista.

 old_list = [1, 2, 3] new_list = [*old_list] new_list.append(4) old_list == [1, 2, 3] new_list == [1, 2, 3, 4] 

El inconveniente obvio de este método es que solo está disponible en Python 3.5+.

Sin embargo, en el momento oportuno, esto parece funcionar mejor que otros métodos comunes.

 x = [random.random() for _ in range(1000)] %timeit a = list(x) %timeit a = x.copy() %timeit a = x[:] %timeit a = [*x] #: 2.47 µs ± 38.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) #: 2.47 µs ± 54.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) #: 2.39 µs ± 58.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) #: 2.22 µs ± 43.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) 

No estoy seguro de si esto sigue siendo real, pero el mismo comportamiento también se aplica a los diccionarios. Mira este ejemplo.

 a = {'par' : [1,21,3], 'sar' : [5,6,8]} b = a c = a.copy() a['har'] = [1,2,3] a Out[14]: {'har': [1, 2, 3], 'par': [1, 21, 3], 'sar': [5, 6, 8]} b Out[15]: {'har': [1, 2, 3], 'par': [1, 21, 3], 'sar': [5, 6, 8]} c Out[16]: {'par': [1, 21, 3], 'sar': [5, 6, 8]} 

Tenga en cuenta que hay algunos casos en los que si ha definido su propia clase personalizada y desea conservar los atributos, debe usar copy.copy() o copy.deepcopy() lugar de las alternativas, por ejemplo en Python 3:

 import copy class MyList(list): pass lst = MyList([1,2,3]) lst.name = 'custom list' d = { 'original': lst, 'slicecopy' : lst[:], 'lstcopy' : lst.copy(), 'copycopy': copy.copy(lst), 'deepcopy': copy.deepcopy(lst) } for k,v in d.items(): print('lst: {}'.format(k), end=', ') try: name = v.name except AttributeError: name = 'NA' print('name: {}'.format(name)) 

Salidas:

 lst: original, name: custom list lst: slicecopy, name: NA lst: lstcopy, name: NA lst: copycopy, name: custom list lst: deepcopy, name: custom list 

Un enfoque muy simple independiente de la versión de python faltaba en las respuestas ya dadas que puede usar la mayor parte del tiempo (al menos yo lo hago):

 new_list = my_list * 1 #Solution 1 when you are not using nested lists 

Sin embargo, si my_list contiene otros contenedores (por ejemplo, listas anidadas), debe usar deepcopy como otros sugirieron en las respuestas anteriores de la biblioteca de copias. Por ejemplo:

 import copy new_list = copy.deepcopy(my_list) #Solution 2 when you are using nested lists 

. Bonificación : si no desea copiar elementos, use (también conocido como copia superficial):

 new_list = my_list[:] 

Entendamos la diferencia entre la Solución # 1 y la Solución # 2

 >>> a = range(5) >>> b = a*1 >>> a,b ([0, 1, 2, 3, 4], [0, 1, 2, 3, 4]) >>> a[2] = 55 >>> a,b ([0, 1, 55, 3, 4], [0, 1, 2, 3, 4]) 

Como puede ver, la Solución # 1 funcionó perfectamente cuando no estábamos usando las listas anidadas. Veamos qué pasará cuando apliquemos la solución # 1 a las listas anidadas.

 >>> from copy import deepcopy >>> a = [range(i,i+4) for i in range(3)] >>> a [[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]] >>> b = a*1 >>> c = deepcopy(a) >>> for i in (a, b, c): print i [[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]] [[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]] [[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]] >>> a[2].append('99') >>> for i in (a, b, c): print i [[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5, 99]] [[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5, 99]] #Solution#1 didn't work in nested list [[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]] #Solution #2 - DeepCopy worked in nested list 

Puedes usar bulit en la función list ():

 newlist=list(oldlist) 

Creo que este código te ayudará.

 new_list = my_list[:] 

new_list = my_list Intenta entender esto. Digamos que my_list está en la memoria del montón en la ubicación X, es decir, my_list está apuntando a la X. Ahora, asignando new_list = my_list estás dejando que new_list apunte a la X. Esto se conoce como Copia superficial.

Ahora, si asigna new_list = my_list[:] Simplemente está copiando cada objeto de my_list a new_list. Esto se conoce como copia profunda.

La otra forma en que puedes hacer esto son:

  • new_list = list(old_list)
  • import copy new_list = copy.deepcopy(old_list)

Le gustará usar deepcopy de la biblioteca estándar de python.

En Python, cuando copia un tipo de datos, los tipos de datos originales y copiados comparten las mismas ubicaciones de memoria . En consecuencia, cualquier cambio realizado en una copia de un objeto se refleja en el objeto original . Por ejemplo considera esto:

 my_lst=[1,2,3,4,5] #Python list print my_lst, ' my_lst (before copy)' my_lst_copy = my_lst=[1,2,3,4,5] #Simple copy of python list my_lst_copy[2] = 55 #Copy of python list changed print my_lst_copy, ' my_lst_copy (copy of python list)' print my_lst, ' my_lst (after copy)' >>>[1, 2, 3, 4, 5] my_lst (before copy) >>>[1, 2, 55, 4, 5] my_lst_copy (copy of python list) >>>[1, 2, 55, 4, 5] my_lst (after copy) 

Como había notado antes, y como notó nuevamente en el ejemplo anterior, el cambio en cualquier elemento de la lista copiada my_list_cp cambia la lista original my_list . La razón de esto es que no ha habido una nueva asignación a my_list_cp .

Puedes contrarrestar lo anterior usando deepcopy desde la biblioteca estándar de python. En copia profunda, una copia de objeto se copia en otro objeto.

 from copy import deepcopy my_lst=[1,2,3,4,5] #Python list print my_lst, ' my_lst (before copy)' my_lst_copy = deepcopy(my_lst) #Python list copied my_lst_copy[2] = 55 #Copy of python list changed print my_lst_copy, ' my_lst_copy (copy of python list)' print my_lst, ' my_lst (after copy)' >>>[1, 2, 3, 4, 5] my_lst (before copy) >>>[1, 2, 55, 4, 5] my_lst_copy (copy of python list) >>>[1, 2, 3, 4, 5] my_lst (after copy) 

En el ejemplo anterior, ves que my_lst no ha cambiado después de copiar.

Puede usar el método list.copy() (python 3.3+): https://docs.python.org/3/library/copy.html new_list = old_list.copy