E0_copy = list(E0)后,我猜E0_copy是E0的深度拷贝,因为id(E0)不等于id(E0_copy)。然后我在循环中修改了E0_copy,但是为什么E0之后不一样了?

E0 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
for k in range(3):
    E0_copy = list(E0)
    E0_copy[k][k] = 0
    #print(E0_copy)
print E0  # -> [[0, 2, 3], [4, 0, 6], [7, 8, 0]]

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

现在看深度复制操作

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

为了解释,list(…)不会递归地复制内部对象。它只生成最外层列表的副本,同时仍然引用相同的内部列表,因此,当您改变内部列表时,更改会反映在原始列表和浅副本中。您可以看到,通过检查id(a[0]) == id(b[0]) where b = list(a),浅复制引用了内部列表。


如果你的列表元素是不可变对象,那么你可以使用这个,否则你必须从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提到的,这已经在复制模块中实现了。


将列表视为树,python中的deep_copy可以最简洁地写成

def deep_copy(x):
    if not isinstance(x, list):
        return x
    else:
        return [deep_copy(elem) for elem in x]

它基本上是以深度优先的方式递归遍历列表。


在Python中,有一个名为copy的模块,它有两个有用的函数:

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

Copy()是一个浅拷贝函数。如果给定的参数是一个复合数据结构,例如一个列表,那么Python将创建另一个相同类型的对象(在这种情况下,是一个新列表),但对于旧列表中的所有内容,只有它们的引用被复制。可以这样想:

newList = [elem for elem in oldlist]

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

但这是错误的!

Deepcopy()实际上保留了原始复合数据的图形结构:

a = [1,2]
b = [a,a] # there's only 1 object a
c = deepcopy(b)

# check the result
c[0] is a # False, a new object a_1 is created
c[0] is c[1] # True, c is [a_1, a_1] not [a_1, a_2]

这是棘手的部分:在deepcopy()过程中,使用哈希表(Python中的字典)将每个旧对象ref映射到每个新对象ref,这防止了不必要的重复,从而保留了复制的复合数据的结构。

官方文档


如果列表的内容是基本数据类型,则可以使用理解式

new_list = [i for i in old_list]

你可以为多维列表嵌套它,比如:

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

下面是一个深度复制2D列表的例子:

  b = [x[:] for x in a]

@Sukrit卡尔拉

No.1: list(), [:], copy.copy()都是浅拷贝。如果一个对象是复合的,它们都不合适。你需要使用copy.deepcopy()。

2 . 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()和[:]是相同的。除了第一层更改外,其他所有层的更改都将被传输。

>>> 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
>>> a
[1, [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]


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



# =========== list() ===========
>>> a = [[1, 2, [3.5, 6]], [4, 5, 6]]
>>> b = list(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 = list(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()函数与list()和[:]相同。他们都是肤浅的拷贝。

有关浅复制和深度复制的更多信息,可以参考这里。

>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = copy.copy(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]]

通过深度复制()

>>> import copy
>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = copy.deepcopy(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 = copy.deepcopy(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, 2, 3], [4, 5, 6]]


如果不允许直接导入模块,可以将自己的deepcopy函数定义为-

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

如果你使用deepcopy给同一个列表赋值, 请使用临时变量。由于某些原因,copy.deepcopy()在尝试使用索引自我更新同一变量时,在对象列表上不起作用

S = S[idx] ->x
S = copy.deepcopy(S[idx])  -> x

VVVV,虽然这工作

Stemp = np.zeros(N,dtype=object)
for ii in range(N):
   Stemp[ii]=copy.deepcopy(S[idx[ii]])
S= copy.deepcopy(Stemp)