While loop with multiple conditions in Python


#1

Hi,

I am trying to solve the exercise at the following link:

https://www.codecademy.com/programs/d2ddb3636e9e6b3c6b87dc85dc0ea065/content-items/192b1c5a7b20eb1345e2914df7f66519/exercises/remove-even-nums

It is required to build a function that removes all the even numbers at the beginning of a list.
For example:

[4, 8, 10, 11, 12, 15]
[4, 8, 10]

in these two cases the code should return, respectively:

[11, 12, 15]
[ ]

The solution provided is the following:

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

I have two questions:

  1. If I swap the two conditions connected by and, the interpreter throws an error (list index out of range). This happens only for the second list (where all numbers are even).
    (i.e. I get an error if I use the following code):
def delete_starting_evens(lst):
 while lst[0]%2 == 0 and len(lst) >= 1:
   lst = lst[1:]
 return lst

Why does this happen? Should not the two conditions be applied at the same time, whatever the order in which they are written?

  1. In my opinion, the code lst = lst[1:] should throw an error when the loop is operating with the second list.
    In fact, after the elements 4 and 8 are removed in the first two iterations, the list becomes lst = [10], and applying the slicing command [1:] on this list means referring to the index 1 of the list. But this list does not have an index 1, it only has index 0.
    Why don’t I get any error?

Thank you very much in advance, this problem kept me awake for several hours last night! :sweat_smile:


#2

The two conditions are different in that the first condition only polls the length of the list (may be 0). An empty list is not an issue. The second condition does poll the list, though, so when attempting to access an element in an empty list it comes back as index out of range.

[]  does not have an index 0.
>>> a = []
>>> a[0]
Traceback (most recent call last):
  File "<pyshell#111>", line 1, in <module>
    a[0]
IndexError: list index out of range
>>> a[0] = 1
Traceback (most recent call last):
  File "<pyshell#112>", line 1, in <module>
    a[0] = 1
IndexError: list assignment index out of range
>>> 

The main reason your code does not raise an exception when written as above (len check first) is because AND short-circuits on falsy. When the length of the list is less than 1, the condition is falsy so evaluation ceases at that point and the second condition is not evaluated.