You are right that slicing doesn't copy the items in the list. However, it does create a new list object.
Your comment suggests a misunderstanding:
# Attempting to modify the element at index 1
l[0:2][-1] = 10
This is not a modification of the element, it's a modification of the list. In other words it is really "change the list so that index 1 now points to the number 10". Since your slice created a new list, you are just changing that new list to point at some other object.
In your comment to oldrinb's answer, you said:
Why are l[0:1]
and l[0:1][0]
different? Shouldn't they both refer to the same object, i.e. the first item of l
?
Aside from the fact that l[0:1]
is a list while l[0:1][0]
is a single element, there is again the same misunderstanding here. Suppose that some_list
is a list and the object at index ix
is obj
. This:
some_list[ix] = blah
. . . is an operation on some_list
. The object obj
is not involved. This can be confusing because it means some_list[ix]
has slightly different semantics depending on which side of the assignment it is on. If you do
blah = some_list[ix] + 2
. . .then you are indeed operating on the object inside the list (i.e., it is the same as obj + 2
). But when the indexing operation is on the left of the assignment, it no longer involves the contained object at all, only the list itself.
When you assign to a list index you are modifying the list, not the object inside it. So in your example l[0]
is the same as l[0:2][0]
, but that doesn't matter; because your indexing is an assignment target, it's modifying the list and doesn't care what object was in there already.