What, if any, is the difference between list and list[:] in python?
7 Answers
li[:] creates a copy of the original list. But it does not refer to the same list object. Hence you don't risk changing the original list by changing the copy created by li[:].
for example:
>>> list1 = [1,2,3]
>>> list2 = list1
>>> list3 = list1[:]
>>> list1[0] = 4
>>> list2
[4, 2, 3]
>>> list3
[1, 2, 3]
Here list2 is changed by changing list1 but list3 doesn't change.
To apply the first list to a variable will create a reference to the original list.
The second list[i] will create a shallow copy.
for example:
foo = [1,2,3]
bar = foo
foo[0] = 4
bar and foo will now be:
[4,2,3]
but:
foo = [1,2,3]
bar = foo[:]
foo[0] = 4
result will be:
bar == [1,2,3]
foo == [4,2,3]
: is to slice.
However, if the list elements are lists themselves, even list1 = list[:] has its problems. Consider:
>>> a = [[1,2,3],[4,5,6],[7,8,9]]
>>> b = a[:]
>>> b[0].remove(2)
>>> b
[[1, 3], [4, 5, 6], [7, 8, 9]]
>>> a
[[1, 3], [4, 5, 6], [7, 8, 9]]
This happens because each list element being copied to b is a list itself, and this copying of lists involves the same problem that occurs with the normal list1 = list2.
The shortest way out that I've found is to explicitly copy every list element this way:
>>> a = [[1,2,3],[4,5,6],[7,8,9]]
>>> b=[[j for j in i] for i in a]
>>> b
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> b[0].remove(2)
>>> b
[[1, 3], [4, 5, 6], [7, 8, 9]]
>>> a
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Of course, for every additional degree of nesting in the nested list, the copying code deepens by an additional inline for loop.
The first one references to the original list. The second one points to the copy of the original list.
Check this out!
>>> a = [1, 2, 3]
>>> b = a
>>> c = a[:]
>>> a == b
True
>>> a is b
True
>>> a == c
True
>>> a is c
False
>>> a.__repr__
<method-wrapper '__repr__' of list object at 0x7f87a9ba3688>
>>> a.__repr__()
'[1, 2, 3]'
>>> b.__repr__
<method-wrapper '__repr__' of list object at 0x7f87a9ba3688>
>>> c.__repr__
<method-wrapper '__repr__' of list object at 0x7f87ad352988>
Notice that both a and b point to the address 0x7f87a9ba3688 whereas, c points to 0x7f87ad352988.
The difference is crystal clear.
Both a and b reference to the original list object.
Whereas, c points to the copy (of the original list) and thus, it is in a different location.