What is the difference between slice assignment that slices the whole list and direct assignment?
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 object- That object is modified, instead of pointing
a_list
at a new object - That object must support
__setitem__
with aslice
index - The object on the right must support iteration
- No name is pointed at the object on the right. If there are no other references to it (such as when it is a literal as in your example), it will be reference counted out of existence after the iteration is complete.
In python, what is the difference between slice with all the element and itself?
numbers[:] = something
is known as slice assignment. It replaces the elements in the selected slice (the whole array in this case), with the elements to the right of the assignment.
numbers = something
is regular assignment, which makes numbers point to something
.
This example illustrates the differences:
numbers = [1, 2, 3]
something = [4, 5, 6]
numbers = something
something[0] = 10
print(numbers) # [10, 5, 6]
Notice how we may have wanted to modify the something
list, but we unexpectedly modified numbers
! Because they point to the same list. However, things are different with slice assignment:
numbers = [1, 2, 3]
something = [4, 5, 6]
numbers[:] = something
something[0] = 10
print(numbers) # [4, 5, 6]
numbers
is still the same.
As pointed by user Tomerikoo in the comments, the slice's size doesn't have to match with whatever it's being replaced with. Which means the following is valid:
numbers = [1, 2, 3]
numbers[:] = [4, 5, 6, 7, 8, 9]
How is this list expanded with the slicing assignment?
Slice assignment replaces the specified part of the list with the iterable on the right-hand side, which may have a different length than the slice. Taking the question at face value, the reason why this is so is because it's convenient.
You are not really assigning to the slice, i.e. Python doesn't produce a slice object that contains the specified values from the list and then changes these values. One reason that wouldn't work is that slicing returns a new list, so this operation wouldn't change the original list.
Also see this question, which emphasizes that slicing and slice assignment are totally different.
Assign value to a list using slice notation with assignee
There is indeed a difference between a[:] = b
and a = b
.
>>> a = [1,2,3,4]
>>> b = [4,5,6,7]
>>> c = [8,9,0,1]
>>> c = b
>>> a[:] = b
>>> b[0] = 0
>>> a
[4, 5, 6, 7]
>>> c
[0, 5, 6, 7]
>>>
When you write a = b
, a is a reference to same list as b: any change in b will affect a
when you write a[:] = b
a is a list initialized with the elements of b: a change in b will not affect a
And there also a difference between a[:] = b
and a = b[:]
.
>>> a = [1,2,3,4]
>>> b = [4,5,6,7]
>>> c = a
>>> a = b[:]
>>> a
[4, 5, 6, 7]
>>> c
[1, 2, 3, 4]
>>> a = [1,2,3,4]
>>> b = [4,5,6,7]
>>> c = a
>>> a[:] = b
>>> a
[4, 5, 6, 7]
>>> c
[4, 5, 6, 7]
With a = b[:]
, you create a new list with the elements from b, if another variable pointed to a it is not affected
With a[:] = b
, you change the elements of a. If another variable pointed to a it is also changed.
Related Topics
Break // in X Axis of Matplotlib
Making Python Loggers Output All Messages to Stdout in Addition to Log File
Python: JSON.Loads Returns Items Prefixing with 'U'
List VS Generator Comprehension Speed with Join Function
How to Check If There Are Duplicates in a Flat List
Draw a Transparent Rectangles and Polygons in Pygame
Pandas 'Count(Distinct)' Equivalent
How to Implement a Python for Range Loop Without an Iterator Variable
"Cloning" Row or Column Vectors
Decode Escaped Characters in Url
How to Create Test and Train Samples from One Dataframe with Pandas
Numpy Array Assignment with Copy
Error When Configuring Tkinter Widget: 'Nonetype' Object Has No Attribute
How to Remove All Characters After a Specific Character in Python
Finding a Key Recursively in a Dictionary