Search code examples
pythonlistsliceshallow-copy

What are the differences between applying list methods and reassignment on a list slice?


I tried these codes on a list slice a[:] when I was learning list methods:

a = list('zyx')
a[:].pop()
print(a)

a = list('zyx')
a[:].append('o')
print(a)

a = list('zyx')
a[:].clear()
print(a)

a = list('zyx')
a[:] = []
print(a)

and the results I got are:

['z', 'y', 'x']
['z', 'y', 'x']
['z', 'y', 'x']
[]

What makes me confused is both the list methods and the reassignment changed the list slice, but why did the reassignment affect the original list while the list methods did not?

I know it might be about shallow copy, but I can not tell exactly why.


Solution

  • Understanding the methods underneath may be the key to success:

    A slice such as a[:] used in an expression calls list.__getitem__(slice(None, None)) where None, None are the start and end of the slice.

    Calling __getitem__ on a list with a slice returns a new list object (shallow copy) made up of that slice. That means a[:].anything() will operate on a temporary new list that was created.

    A slice on left side of the equals (a[:] = value), calls list.__setitem__(slice(None, None), value). In other words, it modifies the existing list - which is what you'd generally expect.

    As @jasonharper noted, modifying a new temporary slice without another reference would be confusing and not very useful; yet another reason for the asymmetry.