Python: deepcopy(list) vs new_list = old_list[:]


问题内容

I’m doing exercise #9 from
http://openbookproject.net/thinkcs/python/english2e/ch09.html and have ran
into something that doesn’t make sense.

The exercise suggests using copy.deepcopy() to make my task easier but I
don’t see how it could.

def add_row(matrix):
    """
        >>> m = [[0, 0], [0, 0]]
        >>> add_row(m)
        [[0, 0], [0, 0], [0, 0]]
        >>> n = [[3, 2, 5], [1, 4, 7]]
        >>> add_row(n)
        [[3, 2, 5], [1, 4, 7], [0, 0, 0]]
        >>> n
        [[3, 2, 5], [1, 4, 7]]
    """

    import copy
    # final = copy.deepcopy(matrix)  # first way
    final = matrix[:]                # second way
    li = []
    for i in range(len(matrix[0])):
        li.append(0)
    # return final.append(li)  # why doesn't this work?
    final.append(li)            # but this does
    return final

I’m confused why the book suggests using deepcopy() when a simple list[:]
copies it. Am I using it wrong? Is my function completely out of wack?

I also have some confusion returning values. the question is documents in the
code above.

TIA


问题答案:

You asked two questions:

Deep vs. shallow copy

matrix[:] is a shallow copy -- it only copies the elements directly
stored in it, and doesn’t recursively duplicate the elements of arrays or
other references within itself. That means:

a = [[4]]
b = a[:]
a[0].append(5)
print b[0] # Outputs [4, 5], as a[0] and b[0] point to the same array

The same would happen if you stored an object in a.

deepcopy() is, naturally, a deep copy -- it makes copies of each of its
elements recursively, all the way down the tree:

a = [[4]]
c = copy.deepcopy(a)
a[0].append(5)
print c[0] # Outputs [4], as c[0] is a copy of the elements of a[0] into a new array

Returning

return final.append(li) is different from calling append and returning
final because list.append does not return the list object itself, it returns
None