Python 如何深度复制列表?
我对列表副本有一些问题: 因此,在我从Python 如何深度复制列表?,python,list,copy,deep-copy,Python,List,Copy,Deep Copy,我对列表副本有一些问题: 因此,在我从'get_edge'获取E0后,我通过调用'E0_copy=list(E0)来复制E0。这里我猜E0\u copy是E0的深度副本,我将E0\u copy传递到'karger(E)中。但是在主功能中。 为什么for循环之前的“print E0[1:10]”的结果与for循环之后的结果不同 下面是我的代码: def get_graph(): f=open('kargerMinCut.txt') G={} for line in f:
'get_edge'
获取E0
后,我通过调用'E0_copy=list(E0)
来复制E0
。这里我猜E0\u copy
是E0
的深度副本,我将E0\u copy
传递到'karger(E)
中。但是在主功能中。为什么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[:]
都是浅拷贝)
用于深度复制列表
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]]
如果您的
列表元素
是不可变对象
,那么您可以使用它,否则您必须使用copy
模块中的deepcopy
您也可以像这样使用最短路径对列表进行深度复制
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]
只是一个递归的深度复制函数
def deepcopy(A):
rt = []
for elem in A:
if isinstance(elem,list):
rt.append(deepcopy(elem))
else:
rt.append(elem)
return rt
编辑:正如Cfreak提到的,这已经在copy
模块中实现了。将列表视为一棵树,python中的deep\u copy可以最简洁地写成
def deep_拷贝(x):
如果不存在(x,列表):
返回x
其他:
返回[x中元素的深拷贝(元素)]
它基本上是以深度优先的方式递归遍历列表。我相信很多程序员都遇到过一两个面试问题,要求他们深度复制链接列表,但是这个问题比听起来更难
在python中,有一个名为“copy”的模块,其中包含两个有用的函数
import copy
copy.copy()
copy.deepcopy()
copy()是一个浅层复制函数,如果给定的参数是一个复合数据结构,例如列表,那么python将创建另一个相同类型的对象(在本例中是新列表),但对于旧列表中的所有内容,只复制它们的引用
# think of it like
newList = [elem for elem in oldlist]
直观地说,我们可以假设deepcopy()将遵循相同的范例,唯一的区别是,对于每个元素,我们将递归地调用deepcopy,(就像mbcoder的答案一样)
但这是错误的强>
deepcopy()实际上保留了原始复合数据的图形结构:
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中的字典)映射:
“旧的对象引用到新的对象引用”,这可以防止不必要的重复,从而保留复制的复合数据的结构
这更像蟒蛇
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]
下面是一个如何深度复制二维列表的示例:
b = [x[:] for x in a]
@苏克里特·卡拉
第一:list()
,[:]
,copy.copy()
都是浅拷贝。如果一个物体是复合物,它们都不合适。您需要使用copy.deepcopy()
第二:b=a
直接,a
和b
具有相同的参考,更改a
与更改b
一样重要
将a设为b
如果将a
直接关联到b
,a
和b
共享一个引用
>a=[[1,2,3],[4,5,6]]
>>>b=a
>>>a
[[1, 2, 3], [4, 5, 6]]
>>>b
[[1, 2, 3], [4, 5, 6]]
>>>a[0]=1
>>>a
[1, [4, 5, 6]]
>>>b
[1, [4, 5, 6]]
>>>a=[[1,2,3],[4,5,6]]
>>>b=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
[[1, 10, 3], [4, 5, 6]]
卷影副本
通过list()
list()
和[:]
是相同的。除第一层更改外,所有其他层的更改都将被传输
>a=[[1,2,3],[4,5,6]]
>>>b=列表(a)
>>>a
[[1, 2, 3], [4, 5, 6]]
>>>b
[[1, 2, 3], [4, 5, 6]]
>>>a[0]=1
>>>a
[1, [4, 5, 6]]
>>>b
[[1, 2, 3], [4, 5, 6]]
>>>a=[[1,2,3],[4,5,6]]
>>>b=列表(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
[[1, 10, 3], [4, 5, 6]]
通过[:]
>a=[[1,2,3],[4,5,6]]
>>>b=a[:]
>>>a
[[1, 2, 3], [4, 5, 6]]
>>>b
[[1, 2, 3], [4, 5, 6]]
>>>a[0]=1
>>>a
[1, [4, 5, 6]]
>>>b
[[1, 2, 3], [4, 5, 6]]
>>>a=[[1,2,3],[4,5,6]]
>>>b=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
[[1, 10, 3], [4, 5, 6]]
list()和[:]更改除第一层以外的其他层
#=============[:]===========
>>>a=[[1,2,3.5,6]],[4,5,6]]
>>>b=a[:]
>>>a
[[1, 2, [3.5, 6]], [4, 5, 6]]
>>>b
[[1, 2, [3.5, 6]], [4, 5, 6]]
>>>a[0][2]=4
>>>a
[[1, 2, 4], [4, 5, 6]]
>>>b
[[1, 2, 4], [4, 5, 6]]
>>>a=[[1,2,3.5,6]],[4,5,6]]
>>>b=a[:]
>>>a
[[1, 2, [3.5, 6]], [4, 5, 6]]
>>>b
[[1, 2, [3.5, 6]], [4, 5, 6]]
>>>a[0][2][0]=999
>>>a
[[1, 2, [999, 6]], [4, 5, 6]]
>>>b
[[1, 2, [999, 6]], [4, 5, 6]]
#=============列表()===========
>>>a=[[1,2,3.5,6]],[4,5,6]]
>>>b=列表(a)
>>>a
[[1, 2, [3.5, 6]], [4, 5, 6]]
>>>b
[[1, 2, [3.5, 6]], [4, 5, 6]]
>>>a[0][2]=4
>>>a
[[1, 2, 4], [4, 5, 6]]
>>>b
[[1, 2, 4], [4, 5, 6]]
>>>a=[[1,2,3.5,6]],[4,5,6]]
>>>b=列表(a)
>>>a
[[1, 2, [3.5, 6]], [4, 5, 6]]
>>>b
[[1, 2, [3.5, 6]], [4, 5, 6]]
>>>a[0][2][0]=999
>>>a
[[1, 2, [999, 6]], [4, 5, 6]]
>>>b
[[1, 2, [999, 6]], [4, 5, 6]]
通过copy()
您将发现copy()
函数与list()
和[:]
相同。它们都是浅拷贝
有关浅拷贝和深拷贝的更多信息,请参考
def copyList(L):
if type(L[0]) != list:
return [i for i in L]
else:
return [copyList(L[i]) for i in range(len(L))]
>>> x = [[1,2,3],[3,4]]
>>> z = copyList(x)
>>> x
[[1, 2, 3], [3, 4]]
>>> z
[[1, 2, 3], [3, 4]]
>>> id(x)
2095053718720
>>> id(z)
2095053718528
>>> id(x[0])
2095058990144
>>> id(z[0])
2095058992192
>>>