variable lista library deepcopy python list copy deep-copy

lista - python copy variable



Copia profunda de una lista en Python (7)

Tengo algún problema con una copia de la lista:

Entonces, después de obtener E0 de ''get_edge'' , hago una copia de E0 llamando ''E0_copy = list(E0)'' . Aquí supongo que E0_copy es una copia profunda de E0 , y paso E0_copy a ''karger(E)'' . Pero en la función principal.
¿Por qué el resultado de ''print E0[1:10]'' antes del bucle for no es el mismo que después del bucle for?

A continuación está mi código:

def get_graph(): f=open(''kargerMinCut.txt'') G={} for line in f: ints = [int(x) for x in line.split()] G[ints[0]]=ints[1:len(ints)] return G def get_edge(G): E=[] for i in range(1,201): for v in G[i]: if v>i: E.append([i,v]) print id(E) return E def karger(E): import random count=200 while 1: if count == 2: break edge = random.randint(0,len(E)-1) v0=E[edge][0] v1=E[edge][1] E.pop(edge) if v0 != v1: count -= 1 i=0 while 1: if i == len(E): break if E[i][0] == v1: E[i][0] = v0 if E[i][1] == v1: E[i][1] = v0 if E[i][0] == E[i][1]: E.pop(i) i-=1 i+=1 mincut=len(E) return mincut if __name__=="__main__": import copy G = get_graph() results=[] E0 = get_edge(G) print E0[1:10] ## this result is not equal to print2 for k in range(1,5): E0_copy=list(E0) ## I guess here E0_coypy is a deep copy of E0 results.append(karger(E0_copy)) #print "the result is %d" %min(results) print E0[1:10] ## this is print2

¡Gracias por adelantado!


Creo que muchos programadores se han encontrado con uno o dos problemas de entrevista en los que se les pide que copien en profundidad una lista vinculada, ¡pero este problema no es tan fácil como parece!

en python, hay un módulo llamado "copiar" con dos funciones útiles

import copy copy.copy() copy.deepcopy()

copy () es una función de copia superficial, si el argumento dado es una estructura de datos compuesta, por ejemplo una lista , entonces python creará otro objeto del mismo tipo (en este caso, una nueva lista ) pero para todo dentro de la lista anterior, solo se copia su referencia

# think of it like newList = [elem for elem in oldlist]

Intuitivamente, podríamos suponer que deepcopy () seguiría el mismo paradigma, y ​​la única diferencia es que por cada elemento llamaremos recursivamente a deepcopy , (al igual que la respuesta de mbcoder)

pero esto está mal!

deepcopy () en realidad conserva la estructura gráfica de los datos compuestos originales:

a = [1,2] b = [a,a] # there''s only 1 object a c = deepcopy(b) # check the result c[0] is a # return False, a new object a'' is created c[0] is c[1] # return True, c is [a'',a''] not [a'',a'''']

esta es la parte difícil, durante el proceso de deepcopy () se usa una tabla hash (diccionario en python) para mapear: "ref old_object en ref new_object", esto evita duplicados innecesarios y así preserva la estructura de los datos compuestos copiados

doc oficial


En cuanto a la lista como árbol, deep_copy en python se puede escribir de forma más compacta

def deep_copy(x): if not isinstance(x, list): return x else: return map(deep_copy, x)


Esto es más pitónico

my_list = [0, 1, 2, 3, 4, 5] # some list my_list_copy = list(my_list) # my_list_copy and my_list does not share reference now.

NOTA: Esto no es seguro con una lista de tipos mutables


Si los list elements su list elements son immutable objects , puede usar esto; de lo contrario, debe utilizar deepcopy desde el módulo de copy .

también puede usar la forma más corta para copiar en profundidad una list como esta.

a = [0,1,2,3,4,5,6,7,8,9,10] b = a[:] #deep copying the list a and assigning it to b print id(a) 20983280 print id(b) 12967208 a[2] = 20 print a [0, 1, 20, 3, 4, 5, 6, 7, 8, 9,10] print b [0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10]


Si los contenidos de la lista son tipos de datos primitivos, puede usar una comprensión

new_list = [i for i in old_list]

Puede anidarlo para listas multidimensionales como:

new_grid = [[i for i in row] for row in grid]


solo una función de copia profunda recursiva.

def deepcopy(A): rt = [] for elem in A: if isinstance(elem,list): rt.append(deepcopy(elem)) else: rt.append(elem) return rt

Editar: Como mencionó Cfreak, esto ya está implementado en el módulo de copy .


E0_copy no es una copia profunda. No hace una copia profunda usando list() (Both list(...) y testList[:] son copias superficiales).

Utiliza copy.deepcopy(...) para copiar profundamente una lista.

deepcopy(x, memo=None, _nil=[]) Deep copy operation on arbitrary Python objects.

Vea el siguiente fragmento:

>>> a = [[1, 2, 3], [4, 5, 6]] >>> b = list(a) >>> a [[1, 2, 3], [4, 5, 6]] >>> b [[1, 2, 3], [4, 5, 6]] >>> a[0][1] = 10 >>> a [[1, 10, 3], [4, 5, 6]] >>> b # b changes too -> Not a deepcopy. [[1, 10, 3], [4, 5, 6]]

Ahora vea la operación de deepcopy

>>> import copy >>> b = copy.deepcopy(a) >>> a [[1, 10, 3], [4, 5, 6]] >>> b [[1, 10, 3], [4, 5, 6]] >>> a[0][1] = 9 >>> a [[1, 9, 3], [4, 5, 6]] >>> b # b doesn''t change -> Deep Copy [[1, 10, 3], [4, 5, 6]]