You must be aware, however, that all of these techniques perform a shallow copy. That is, they create a new list containing references to the same objects as the source list, but they don't copy the referred-to objects. To demonstrate this, we'll use nested lists, with the inner lists serving as mutable objects. Here's a list containing two elements, each of which is itself a list:
>>> a = [ [1, 2], [3, 4] ]
We copy this list using a full slice:
>>> b = a[:]
And convince ourselves that we do in fact have distinct lists:
>>> a is b
False
With equivalent values:
>>> a == b
True
Notice, however, that the references within these distinct lists refer not only to equivalent objects:
>>> a[0]
[1, 2]
>>> b[0]
[1, 2]
But, in fact, to the same object:
>>> a[0] is b[0]
True
Copies are shallow. When a list is copied the references to the containing objects (yellow diamonds) are copied, but the referred to objects (blue rectangles) are not, as shown in the following diagram:
This situation holds until we rebind the first element of a to a newly constructed list:
>>> a[0] = [8, 9]
Now the first elements of a and b refer to different lists:
>>> a[0]
[8, 9]
>>> b[0]
[1, 2]
The first elements of lists a and b are now uniquely owned, whereas the second elements are shared, as shown in the following diagram:
The second elements of both a and b still refer to the same object. We'll demonstrate this by mutating that object through the a list:
>>> a[1].append(5)
>>> a[1]
[3, 4, 5]
We see the change reflected through the b list:
>>> b[1]
[3, 4, 5]
Modifying an object referred to by two lists, as shown in the following diagram:
For completeness, here is the final state of both the a and b lists:
>>> a
[[8, 9], [3, 4, 5]]
>>> b
[[1, 2], [3, 4, 5]]
The final state of list a.
The final state of list b:
If you need to perform true deep copies of hierarchical data structures like this – which in our experience is a rarity – we recommend taking a look at the copy module in the Python Standard Library.