在Python中深入复制列表

我有一个列表副本的问题:

所以当我从'get_edge'得到E0后,我通过调用'E0_copy = list(E0)'复制E0 。 在这里,我猜E0_copyE0的深层拷贝,我把E0_copy传入'karger(E)' 。 但在主要function。
为什么for循环之前的'print E0[1:10]'的结果与for循环之后的结果不一样?

以下是我的代码:

 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 

提前致谢!

E0_copy不是深层复制。 您不要使用list()list(...)testList[:]是浅拷贝)进行深层复制。

您可以使用copy.deepcopy(...)来深入复制列表。

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

看到下面的代码片断 –

 >>> 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]] 

现在看到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]] 

我相信很多程序员遇到了一两个面试问题,他们被要求深度复制一个链表,但这个问题并不像听起来那么简单!

在python中,有一个叫做“copy”的模块,有两个有用的function

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

copy()是一个浅拷贝函数,如果给定的参数是一个复合数据结构,例如一个列表 ,那么python将创build另一个相同types的对象(在本例中是一个新的列表 )只有他们的参考被复制

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

直觉上,我们可以假设deepcopy()遵循相同的范例,唯一的区别是对于每个elem,我们将recursion调用deepcopy (就像mbcoder的答案一样)

但这是错误的!

deepcopy()实际上保留了原始复合数据的graphics结构:

 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''] 

这是棘手的部分,在deepcopy()过程中散列表(Python中的字典)用于映射:“old_object ref到new_object ref”,这防止不必要的重复,从而保留复制的组合数据的结构

官方文件

如果你的list elementsimmutable objects那么你可以使用这个,否则你必须从copy模块使用deepcopy

您也可以使用最短的方式来深度拷贝像这样的list

 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] 

关于列表树,python中的deep_copy可以写得最紧凑

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

只是一个recursion的深层复制function。

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

编辑:正如Cfreak提到的,这已经在copy模块中实现。

这是比较pythonic

 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. 

如果列表的内容是原始的,你可以使用理解

 new_list = [i for i in old_list] 

您可以将其嵌套为多维列表,如下所示:

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