Why doesn’t step 3 produce an index error?

Why doesn’t step 3 produce an index error?

The way I understand this code to run is if the conditions are met, then take everything form index 1 and beyond and make it it’s own list. But if there is only one element in the list with an index of zero how is it able to reference elements that are not there?

Hello! Would you mind posting the code, please? Also, make sure to format it correctly.

I’m not sure what happened, but I responded to a message in another thread and it seems that my question was moved to it’s own thread.

Any way, I have several questions about the delete starting even numbers coding challenge.

The prompt reads "
Write a function called delete_starting_evens() that has a parameter named lst .
The function should remove elements from the front of lst until the front of the list is not even. The function should then return lst .
For example if lst started as [4, 8, 10, 11, 12, 15] , then delete_starting_evens(lst) should return [11, 12, 15] .
Make sure your function works even if every element in the list is even!"

My initial response was this:

def delete_starting_evens(lst):
  for num in lst:
    if len(lst) > 0 or num % 2 == 0 :
      lst.pop(0)
    return lst

It seems that this only removed the first two elements of the list and then stops iterating. Could you explain why please?

I also don’t understand why the solution works. the solution that is listed reads

def delete_starting_evens(lst):
  while (len(lst) > 0 and lst[0] % 2 == 0):
    lst = lst[1:]
  return lst

It seems to me that this wouold only work until there is on number left in the list and then I would expect an index error to pop up because the code is referencing items in the list that don’t exist.

Your return statement is inside the for loop, meaning the for loop will only iterate once before reaching the return statement. On reaching that, the loop will end, and so will the function.

Correcting that still didn’t yield the correct answer.

def delete_starting_evens(lst):
  for num in lst:
    if len(lst) > 0 and num % 2 == 0:
      lst.pop(0)
  return lst

print(delete_starting_evens([4, 8, 10, 11, 12, 15]))
print(delete_starting_evens([4, 8, 10]))

This yields:
[11, 12, 15]
[10]
So it worked for the first but not for the second.

I just noticed that too. The problem is caused by the fact that your loop is iterating through the lst list (using for num in lst), but you’re also modifying lst. In general, be very careful when modifying the object you’re iterating through.


Consider other types of loop here. A for loop is used when you want to do something for a certain (known) amount of times. A while loop is used when you want to do something until something happens. (In general)…

Gotcha that makes sense. Thank you! Did you get a chance to look at my other question in this thread?

1 Like

The solution code by CC?

I think it has to do with trailing list items (or something with a similar name). Essentially, since you’re list slicing, not just taking an item at a specific index, if you have a list with all evens, when you get to your list being equal to say, [2], doing lst[1:] slices the list and essentially takes everything after the first element (the element with the index 0), which in our case would be nothing, or an empty list ([]).

A pretty bad analogy

Consider a list lst = [2]:
If I laid out a series of dollar notes in ascending order: $5, $10, $20, $50, $100 and then told you that you can have everything to the right of the $100 bill. What do you take? Well, since there’s nothing to the right of it, you take nothing, but the instruction still makes sense. That would be list slicing (lst[1:] in our case).

Alternatively, if I put just a single $5 bill on the table, and said, “you can take the second $5 note,” that wouldn’t make sense, as I’ve only put one on the table. That would be like trying to access an element of a list by an index that is out of range (lst[1] in our case).

I hope that helps (and that my analogy made a modicum of sense)!

I still find it a bit confusing, but I can just accept that. Now just one more question. How come when I reverse the position of the two conditional statements, it prints an index.

This is the correct solution:

def delete_starting_evens(lst):
  while (len(lst) > 0 and lst[0] % 2 == 0):
    lst = lst[1:]
  return lst

But his produces an index error.

def delete_starting_evens(lst):
  while lst[0] % 2 == 0 and len(lst) > 0:
    lst = lst[1:]
  return lst

I’m confused!

That is because the while loop evaluates from left to right. So with your first example, say the list is [], it checks the length of the list. Since [] has a length of zero, the loop stops right there, and the next condition (since there’s an and operator) isn’t evaluated. With your second example; however, the first thing the while loop does at the start of every iteration is check whether the first item in the list (item 0 if you will) is even. Now, if you have an empty list ([]), then there is not “first element,” and so an index error is thrown there.

I hope that helps!