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?
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.