What is the difference between list and list[:] in python?
Question:
What, if any, is the difference between list
and list[:]
in python?
Answers:
The latter is a reference to a copy of the list and not a reference to the list. So it’s very useful.
>>> li = [1,2,3]
>>> li2 = li
>>> li3 = li[:]
>>> li2[0] = 0
>>> li
[0, 2, 3]
>>> li3
[1, 2, 3]
When reading, list
is a reference to the original list, and list[:]
shallow-copies the list.
When assigning, list
(re)binds the name and list[:]
slice-assigns, replacing what was previously in the list.
Also, don’t use list
as a name since it shadows the built-in.
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.
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.
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.
Another useful example is when assigning a different type to a list and list[:]. for example,
l = [1,2,3]
a = numpy.array([4,5,6])
l = a
print(l)
The result is a numpy array:
array([4, 5, 6])
while,
l = [1,2,3]
a = numpy.array([4,5,6])
l[:] = a
print(l)
the result is a list:
[4, 5, 6]
What, if any, is the difference between list
and list[:]
in python?
The latter is a reference to a copy of the list and not a reference to the list. So it’s very useful.
>>> li = [1,2,3]
>>> li2 = li
>>> li3 = li[:]
>>> li2[0] = 0
>>> li
[0, 2, 3]
>>> li3
[1, 2, 3]
When reading, list
is a reference to the original list, and list[:]
shallow-copies the list.
When assigning, list
(re)binds the name and list[:]
slice-assigns, replacing what was previously in the list.
Also, don’t use list
as a name since it shadows the built-in.
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.
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.
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.
Another useful example is when assigning a different type to a list and list[:]. for example,
l = [1,2,3]
a = numpy.array([4,5,6])
l = a
print(l)
The result is a numpy array:
array([4, 5, 6])
while,
l = [1,2,3]
a = numpy.array([4,5,6])
l[:] = a
print(l)
the result is a list:
[4, 5, 6]