Hello, I’ve been working on challenge as in topic and encountered confusing problem:
Here is my code with debugs inserted:
lst_updated = lst
print("lst: ", lst) #debug1
print("lst_updated: ", lst_updated) #debug2
for x in lst:
print("x to check: ", x) #debug3
if (x % 2 == 0):
print(x, " is even") #debug4
print(delete_starting_evens([4, 8, 10]))
Eventually I’ve replaced line 9 with :
lst_updated = lst_updated[1:]
and it works fine.
My question is: why does for loop skip one of the ‘lst’ values (8) during the iteration?
Any modification of ‘lst_updated’ (even inside the loop) should have zero impact on iteration process imo.
When you comment
lst_updated.pop(0) line iteration proceeds as expected.
the problem originates in my attempt to create a list copy:
lst_updated = lst.copy()
solves all the problems, however there has to be some difference between how lst_updated.pop(0) and lst_updated = lst_updated[1:] work.
Hey there and welcome to the forums!!
As you discovered it has to do with your copy. In Python any assignment done involves a pointer to the object in question. Let’s say you create a list named
a, and it is stored at position 5 (for simplicity). If you assign a new variable
b to equal
b = a than b points to that same spot in memory:
If you were using say a (integer/string/tuple) this wouldn’t cause any weird behavior because these are non mutable (they can’t be changed), any action on
b will create a new variable and not effect
a. However something like a list can be mutated, so an action on
>>> a = [1, 2, 3]
>>> b = a
So what’s different between
b = b[1:]?
We’re using an assignment in the latter, yet not it the former. While the
.pop() method modifies the original object, a string slice returns a new one. We don’t actually modify the original, we make a copy following certain parameters and return that.
Now as you saw we can preserve the original list by making a full copy of it using
list(lst), however making a copy like this is not the most efficient. Suppose we have a list that’s thousands of numbers long and only the last number is odd? Copying the original and then modifying the rest might not be the best idea. Instead we could loop read through the list, and when we find the first odd, return a slice of that point through the rest of the list.
Up to you if you want to look at one way or not.
for i in range(len(lst)):
if (lst[i] % 2):
Hello. I am just staring learning Phyton. Can anybody help me to understand why the does not work. What did I miss?
for num in lst:
while num % 2 == 0:
if num % 2 == 1:
print(delete_starting_evens([4, 8, 10, 11, 12, 15]))
Hello @codeslayer51797, welcome to the forums!
The problem here occurs because you’re using a
while loop inside a
for loop. The problem is that the first iteration of your
for loop sets
num equal to the first element of the list. Then, your nested
while loop will continue to
remove items from the list indefinitely (if
num is even).
This happens because the
while loop condition is checking if
num is even, and since
num stays the same (assuming the first element of the list is even, and therefore
num is even), your
while loop will continue looping until the
remove() function throws an error saying that there’s no instance of
As an aside, it’s considered bad practise to modify the list you’re iterating through, as it can lead to some very weird behaviour.