Reputation: 11
my_list = [1,2,3]
for v in range (len(my_list)):
my_list.insert(1,my_list[v])
print(my_list)
#outputs [1,1,1,1,2,3]
I am getting tripped up on why the value of V is set to 1 instead of iterating through the other number found in the list. I've tried reading up on W3 schools but still confused
Upvotes: 0
Views: 3369
Reputation: 1
Found this website with an explantion on this: Iterate a list using range() and for loop. https://pynative.com/python-range-function/ "When you iterate the list only using a loop, you can access only items. When you iterate the list only using a loop, you can only access its items, but when you use range() along with the loop, you can access the index number of each item.
The advantage of using range() to iterate a list is that it allows us to access each item’s index number. Using index numbers, we can access as well as modify list items if required."
Upvotes: 0
Reputation: 29055
The len(my_list)
in the range constructor is evaluated once, at the top of the first iteration of the loop, where the length of my_list is 3. This results in the loop variable v
being set to 0, 1, and 2 as the loop iterates.
Inside the loop, you insert into the list at the second position (i.e. just after the first element of the list) the value of the existing element v
of the list. v
changes on each iteration (0, 1, 2) as you expect. But, so does my_list
, since you are inserting an element with each iteration. So you get the following transformation of my_list:
Start: my_list = [ 1 2 3 ]
v = 0: my_list[0] = 1 -> my_list = [ 1 *1* 2 3 ] (*X* indicates inserted element)
v = 1: my_list[1] = 1 -> my_list = [ 1 *1* 1 2 3 ]
v = 2: my_list[2] = 1 -> my_list = [ 1 *1* 1 1 2 3 ]
Essentially, as you prepend elements to the list, the indices of the existing elements are shifting to the right.
Upvotes: 1
Reputation: 5409
The reason isn't exactly that you're modifying the list you're iterating over-- it's because range
produces an immutable sequence of a fixed length, created exactly once. Therefore, the number of iterations of the for loop is based on len(my_list)
at the beginning, which is 3. The list.insert(i, x)
method puts x in index i, and shoves the old elements at indices (i, i+1 ...) to the right.
Thus your code is equivalent to:
my_list = [1,2,3]
for v in range(3):
my_list.insert(1, my_list[v])
And, if we put parentheses around the new element just inserted in each of the 3 iterations:
my_list = [1, 2, 3]
Insert (my_list[0] == 1) at position 1
my_list = [1, (1), 2, 3]
Insert (my_list[1] == 1) at position 1
my_list = [1, (1), 1, 2, 3]
Insert (my_list[2] == 1) at position 1
my_list = [1, (1), 1, 1, 2, 3]
While this isn't as dangerous as iterating over the list directly while modifying it, the best way to avoid unexpected behavior is to make a copy of the list beforehand, and index into a different list than the one you're modifying.
Upvotes: 2
Reputation: 31
This is because you insert the value 1 before the #1 position in the list, but because the list updates every iteration, the value in the #1 position is always 1. to see this clearly, you can print the list in every iteration
[1,1,2,3]
[1,1,1,2,3]
[1,1,1,1,2,3]
the only thing not updating is the range() that was set to the length of the original list (range(0,3)->v=0,v=1,v=2)
Upvotes: 2
Reputation: 143
You can add a print statement in the loop as follows which will make it easier to understand.
my_list = [1,2,3]
for v in range (len(my_list)):
my_list.insert(1,my_list[v])
print(f"mylist: {my_list}")
print(f"mylist[v]: {my_list[v]}")
print(f"v: {v}")
print(my_list)
above code results:
mylist: [1, 1, 2, 3]
mylist[v]: 1
v: 0
mylist: [1, 1, 1, 2, 3]
mylist[v]: 1
v: 1
mylist: [1, 1, 1, 1, 2, 3]
mylist[v]: 1
v: 2
[1, 1, 1, 1, 2, 3]
Upvotes: 1