I see at many places the use of slice assignment for list
s. I am able to understand its use when used with (non-default) indices, but I am not able to understand its use like:
a_list[:] = ['foo', 'bar']
How is that different from
a_list = ['foo', 'bar']
?
Slice assignment is a special syntax for lists, where you can insert, delete, or replace contents from a list: Insertion: >>> a = [1, 2, 3] >>> a[0:0] = [-3, -2, -1, 0] >>> a [-3, -2, -1, 0, 1, 2, 3]
In Python, list slicing is a common practice and it is the most used technique for programmers to solve efficient problems. Consider a python list, In-order to access a range of elements in a list, you need to slice a list. One way to do this is to use the simple slicing operator i.e. colon(:)
In short, slicing is a flexible tool to build new lists out of an existing list. Python supports slice notation for any sequential data type like lists, strings, tuples, bytes, bytearrays, and ranges. Also, any new data structure can add its support as well.
Does a slice of an entire list create a new object? The short answer Slicing lists does not generate copies of the objects in the list; it just copies the references to them. That is the answer to the question as asked.
a_list = ['foo', 'bar']
Creates a new list
in memory and points the name a_list
at it. It is irrelevant what a_list
pointed at before.
a_list[:] = ['foo', 'bar']
Calls the __setitem__
method of the a_list
object with a slice
as the index, and a new list
created in memory as the value.
__setitem__
evaluates the slice
to figure out what indexes it represents, and calls iter
on the value it was passed. It then iterates over the object, setting each index within the range specified by the slice
to the next value from the object. For list
s, if the range specified by the slice
is not the same length as the iterable, the list
is resized. This allows you to do a number of interesting things, like delete sections of a list:
a_list[:] = [] # deletes all the items in the list, equivalent to 'del a_list[:]'
or inserting new values in the middle of a list:
a_list[1:1] = [1, 2, 3] # inserts the new values at index 1 in the list
However, with "extended slices", where the step
is not one, the iterable must be the correct length:
>>> lst = [1, 2, 3] >>> lst[::2] = [] Traceback (most recent call last): File "<interactive input>", line 1, in <module> ValueError: attempt to assign sequence of size 0 to extended slice of size 2
The main things that are different about slice assignment to a_list
are:
a_list
must already point to an objecta_list
at a new object__setitem__
with a slice
indexThe difference is quite huge! In
a_list[:] = ['foo', 'bar']
You modify a existing list that was bound to the name a_list
. On the other hand,
a_list = ['foo', 'bar']
assigns a new list to the name a_list
.
Maybe this will help:
a = a_list = ['foo', 'bar'] # another name for the same list a_list = ['x', 'y'] # reassigns the name a_list print a # still the original list a = a_list = ['foo', 'bar'] a_list[:] = ['x', 'y'] # changes the existing list bound to a print a # a changed too since you changed the object
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With