I thought I understood Python slicing operations, but when I tried to update a sliced list, I got confused:
>>> foo = [1, 2, 3, 4]
>>> foo[:1]
The main thing to notice here is that foo[:] will return a copy of itself and then the indexing [1] will be applied on the copied list that was returned
# indexing is applied on copied list
(foo[:])[1] = 'two'
^
copied list
You can view this if you retain a reference to the copied list. So, the foo[:][1] = 'two' operation can be re-written as:
foo = [1, 2, 3, 4]
# the following is similar to foo[:][1] = 'two'
copy_foo = foo[:]
copy_foo[1] = 'two'
Now, copy_foo has been altered:
print(copy_foo)
# [1, 'two', 3, 4]
But, foo remains the same:
print(foo)
# [1, 2, 3, 4]
In your case, you didn't name the intermediate result from copying the foo list with foo[:], that is, you didn't keep a reference to it. After the assignment to 'two' is perfomed with foo[:][1] = 'two', the intermediate copied list ceases to exist.