Let's start from the beginning and explore this question.
So let's suppose you have two lists:
list_1 = ['01', '98']
list_2 = [['01', '98']]
And we have to copy both lists, now starting from the first list:
So first let's try by setting the variable copy
to our original list, list_1
:
copy = list_1
Now if you are thinking copy copied the list_1, then you are wrong. The id
function can show us if two variables can point to the same object. Let's try this:
print(id(copy))
print(id(list_1))
The output is:
4329485320
4329485320
Both variables are the exact same argument. Are you surprised?
So as we know, Python doesn't store anything in a variable, Variables are just referencing to the object and object store the value. Here object is a list
but we created two references to that same object by two different variable names. This means that both variables are pointing to the same object, just with different names.
When you do copy = list_1
, it is actually doing:
Here in the image list_1 and copy are two variable names, but the object is same for both variable which is list
.
So if you try to modify copied list then it will modify the original list too because the list is only one there, you will modify that list no matter you do from the copied list or from the original list:
copy[0] = "modify"
print(copy)
print(list_1)
Output:
['modify', '98']
['modify', '98']
So it modified the original list:
Now let's move onto a Pythonic method for copying lists.
copy_1 = list_1[:]
This method fixes the first issue we had:
print(id(copy_1))
print(id(list_1))
4338792136
4338791432
So as we can see our both list having different id and it means that both variables are pointing to different objects. So what actually going on here is:
Now let's try to modify the list and let's see if we still face the previous problem:
copy_1[0] = "modify"
print(list_1)
print(copy_1)
The output is:
['01', '98']
['modify', '98']
As you can see, it only modified the copied list. That means it worked.
Do you think we're done? No. Let's try to copy our nested list.
copy_2 = list_2[:]
list_2
should reference to another object which is copy of list_2
. Let's check:
print(id((list_2)), id(copy_2))
We get the output:
4330403592 4330403528
Now we can assume both lists are pointing different object, so now let's try to modify it and let's see it is giving what we want:
copy_2[0][1] = "modify"
print(list_2, copy_2)
This gives us the output:
[['01', 'modify']] [['01', 'modify']]
This may seem a little bit confusing, because the same method we previously used worked. Let's try to understand this.
When you do:
copy_2 = list_2[:]
You're only copying the outer list, not the inside list. We can use the id
function once again to check this.
print(id(copy_2[0]))
print(id(list_2[0]))
The output is:
4329485832
4329485832
When we do copy_2 = list_2[:]
, this happens:
It creates the copy of list, but only outer list copy, not the nested list copy. The nested list is same for both variable, so if you try to modify the nested list then it will modify the original list too as the nested list object is same for both lists.
What is the solution? The solution is the deepcopy
function.
from copy import deepcopy
deep = deepcopy(list_2)
Let's check this:
print(id((list_2)), id(deep))
4322146056 4322148040
Both outer lists have different IDs. Let's try this on the inner nested lists.
print(id(deep[0]))
print(id(list_2[0]))
The output is:
4322145992
4322145800
As you can see both IDs are different, meaning we can assume that both nested lists are pointing different object now.
This means when you do deep = deepcopy(list_2)
what actually happens:
Both nested lists are pointing different object and they have separate copy of nested list now.
Now let's try to modify the nested list and see if it solved the previous issue or not:
deep[0][1] = "modify"
print(list_2, deep)
It outputs:
[['01', '98']] [['01', 'modify']]
As you can see, it didn't modify the original nested list, it only modified the copied list.
new_list = my_list
just assigns the namenew_list
to the objectmy_list
refers to.