How to Copy a List of Lists in Python

To copy a list of lists in Python, or a list containing any other complex types, use the deepcopy function in the copy module. Example: import copy; list2 = copy.deepcopy(list1).

Can I just use list.copy?

It might be tempting to just use the built-in .copy() method for a Python list to make a copy of it. However, this will only create a shallow copy. This is fine if you just have a list of scalar values like strings or integers, but if you have a list of complex values (such as lists), this won’t be enough.

In Python, if you have an instance of an object stored in a variable, that variable really only contains a number that acts as a reference to that object. If you’re familiar with pointers in C/C++, you know what I mean. When you use the regular .copy method on an object, you’re not actually creating a new separate version of that object with identical values like you’d expect, you’re just copying the number which represents the actual object.

Let’s take a look at an example:

list_of_lists = [["a", "b", "c"], [1, 2, 3]]
list_of_lists2 = list_of_lists.copy()

print(list_of_lists)
print(list_of_lists2)

list_of_lists[0].append("foo")

print(list_of_lists)
print(list_of_lists2)
Python

Here, we have a list with two other lists inside it. What those lists contain doesn’t matter, it’s only important that this is a list of lists, which means our .copy method call on line 2 isn’t going to work properly. On line 7, we append a string to the first list, then print out both lists to see what they contain.

Here’s the result:

[['a', 'b', 'c'], [1, 2, 3]]
[['a', 'b', 'c'], [1, 2, 3]]
[['a', 'b', 'c', 'foo'], [1, 2, 3]]
[['a', 'b', 'c', 'foo'], [1, 2, 3]]

As you can see, both of the lists changed. That means that what was copied only a reference.

Shallow vs deep copies

You may have heard the terms “shallow copy” and “deep copy” before. What these mean is exactly what it sounds like. When you call list.copy on a list, it’s just making a shallow copy, which means it’s not looking any deeper than the top layer of that list. If you have a list of lists, that method will only copy references to the sub-lists.

Deep copies, on the other hand, are actually looking beyond the top layer of the list and creating copies of any complex types found in there, which is likely what you want.

Use copy.deepcopy

Luckily, the Python standard library comes with a module called copy that has a function in it that does exactly what we want.

Here’s an example:

import copy

list_of_lists = [["a", "b", "c"], [1, 2, 3]]
list_of_lists2 = copy.deepcopy(list_of_lists)

print(list_of_lists)
print(list_of_lists2)

list_of_lists[0].append("foo")

print(list_of_lists)
print(list_of_lists2)
Python

Just like the previous example, we start with a list of lists, but then rather than calling list.copy, we use copy.deepcopy, then we go on to modify the first element of the first list in the same way as before.

Here’s our new output:

[['a', 'b', 'c'], [1, 2, 3]]
[['a', 'b', 'c'], [1, 2, 3]]
[['a', 'b', 'c', 'foo'], [1, 2, 3]]
[['a', 'b', 'c'], [1, 2, 3]]

As you can see, modifying that element does not modify it in both places. This is because we’ve made a deep copy of the original list!

Conclusion

When trying to make a copy of a list of lists in Python, you can’t just use the built-in list.copy method. Well, you can, but all you’ll get is a shallow copy. That’s probably not what you want, because both lists now just contain references to the same sub-lists in memory. If you modify one, you’ll modify the other, likely defeating the purpose of making a copy in the first place. What you should do instead is use the copy.deepcopy function found in the copy module – this will look at each element in the list recursively and make a copy of any list (or other complex type such as dict) that it finds.