I want to toggle every second element of a list:
s = [False] * 5
for item in s[::2]:
item = not item
print(s)
But it doesn't work.
[False, False, False, False, False]
This however, works as expected:
for i in range(0, len(s), 2):
s[i] = not s[i]
print(s)
[True, False, True, False, True]
Why is this happening?
Answer
The reason your first approach doesn't work as expected is because you're modifying a copy of the list slice, not the original list itself.
Explanation of the first approach:
s = [False] * 5
for item in s[::2]:
item = not item
print(s)
In this code:
s[::2]
creates a slice of the lists
that includes every second element starting from index0
. However, this slice is a new list that contains the values of the original list, not references to the original elements ins
.- The
item = not item
line modifiesitem
, which is a local variable inside the loop. It does not modify the original lists
becauseitem
is just a copy of the list's values, not a reference to the elements in the original list. - Therefore, the list
s
remains unchanged.
Why the second approach works:
for i in range(0, len(s), 2):
s[i] = not s[i]
print(s)
Here:
- You iterate directly over the indices of the list (
i
), not over a slice. This allows you to modify the original list in place by accessings[i]
and settings[i] = not s[i]
. - This way, the original list
s
gets updated as expected.
How to fix the first approach:
If you want the first approach to work, you need to directly modify the elements of the list. You can do this by iterating over the indices as in the second approach, or by using list comprehension to modify the original list.
Here's how you can fix the first approach:
Approach 1: Modify directly in the loop using indices:
s = [False] * 5
for i in range(0, len(s), 2):
s[i] = not s[i]
print(s)
Approach 2: Using list comprehension:
If you want to use slicing or a more functional approach, you can use list comprehension to modify the list:
s = [False] * 5
s = [not item if i % 2 == 0 else item for i, item in enumerate(s)]
print(s)
Both of these methods will give you the expected output:
[True, False, True, False, True]
Summary:
The first approach doesn't work because you're working with a slice of the list, not the original list. The second approach works because you modify the original list directly using indices.