1

我刚刚开始编程,并且正在研究 Python 的“如何像计算机科学家一样思考”。在第 9 章进行练习之前,我没有遇到任何问题:

def add_column(matrix):

    """
    >>> m = [[0, 0], [0, 0]]
    >>> add_column(m)
    [[0, 0, 0], [0, 0, 0]]
    >>> n = [[3, 2], [5, 1], [4, 7]]
    >>> add_column(n)
    [[3, 2, 0], [5, 1, 0], [4, 7, 0]]
    >>> n
    [[3, 2], [5, 1], [4, 7]]
    """

代码应该使上述 doctest 通过。我被困在最后一个测试中:让原始列表不受影响。我查找了解决方案,如下所示:

x = len(matrix)

matrix2 = [d[:] for d in matrix]
for z in range(x):
    matrix2[z] += [0]
return matrix2

我的问题是:为什么第二行不能是:

matrix2 = matrix[:]

当此行到位时,原始列表将被编辑以包含添加元素。“如何成为..”指南听起来像是克隆创建了一个可以在不影响原始列表的情况下进行编辑的新列表。如果这是真的,这里发生了什么?如果我使用:

matrix2 = copy.deepcopy(matrix)

一切正常,但我并不认为克隆会失败......任何帮助将不胜感激!

4

2 回答 2

1

In your case, matrix contains other lists, so when you do matrix[:], you are cloning matrix, which contains references to other lists. Those are not cloned too. So, when you edit these, they are still the same in the original matrix list. However, if you append an item to the copy (matrix[:]), it will not be appended to the original list.

To visualize this, you can use the id function which returns a unique number for each object: see the docs.

a = [[1,2], [3,4], 5]
print 'id(a)', id(a)
print '>>', [id(i) for i in a]

not_deep = a[:]
# Notice that the ids of a and not_deep are different, so it's not the same list
print 'id(not_deep)', id(not_deep)
# but the lists inside of it have the same id, because they were not cloned!
print '>>', [id(i) for i in not_deep]

# Just to prove that a and not_deep are two different lists
not_deep.append([6, 7])
print 'a items:', len(a), 'not_deep items:', len(not_deep)

import copy
deep = copy.deepcopy(a)
# Again, a different list
print 'id(deep)', id(deep)
# And this time also all the nested list (and all mutable objects too, not shown here)
# Notice the different ids
print '>>', [id(i) for i in deep]

And the output:

id(a) 36169160
>> [36168904L, 35564872L, 31578344L]
id(not_deep) 35651784
>> [36168904L, 35564872L, 31578344L]
a items: 3 not_deep items: 4
id(deep) 36169864
>> [36168776L, 36209544L, 31578344L]
于 2012-04-27T17:19:10.403 回答
0

Say you have nested lists, copying will only copy the references to those nested lists.

>>> a = [1]
>>> b = [2]
>>> c = [a, b]
>>> c
[[1], [2]]
>>> d = c[:]
>>> d
[[1], [2]]
>>> d[1].append(2)
>>> d
[[1], [2, 2]]
>>> c
[[1], [2, 2]]

As where, with copy.deepcopy():

>>> d = copy.deepcopy(c)
>>> d[1].append(2)
>>> c
[[1], [2]]
>>> d
[[1], [2, 2]]

This is true of any mutable items. copy.deepcopy() will attempt to make sure that they are copied too.

It's also worth noting that using d = c[:] to copy a list isn't a very clear syntax anyway. A much better solution is d = list(c) (list() returns a new list from any iterable, including another list). Even more clear, obviously, is copy.copy().

于 2012-04-27T17:17:29.983 回答