Search code examples
pythonwhile-loopbooleanlogical-operators

switching sides of `and` statement in while loop boolean


My problem is that I want to write a function newlist, that takes in a list of numbers as the parameter. It then returns a new list based on the parameter. The new list contains the same values of the original list up until it reaches the number 7.

my code that works:

def newlist(mylst):
    newlst = []
    idx = 0
    while (idx < len(mylst)) and (mylst[idx] != 7):
        newlst.append(mylst[idx])
        idx += 1
    return newlst

now when I switch the sides of the and statement like this:

while (mylst[idx] != 7) and (idx < len(mylst)):

it tells me that this is wrong and when passing a list as parameter, the index is out of range. My question is why does it make a difference with what side of the and statement I start? I thought that the boolean is only True if both statements are True, regardless of order?


Solution

  • The difference is due to the fact that the and operator uses short-circuiting. This means that if the first operand is false, then the second operand is not evaluated.

    In the following:

    (idx < len(mylst)) and (mylst[idx] != 5)
    

    The first operand is (idx < len(mylst)). This checks whether idx is in range. If it is, then the second operand, which uses idx as an index into mylst, is evaluated. But if it isn't, then evaluation stops and the result of the expression is False. In this way, it will never index out of bounds, because the first operand guards the evaluation of the second.

    The second version is:

    (mylst[idx] != 5) and (idx < len(mylst))
    

    Here, the operands are reversed. As a result, if idx is out of range, it will still try to use it as an index into mylst, causing an error.

    So the two versions have a very significant difference. The first version safely checks if idx is within range before attempting to use it as an index, while the second does not.