2

I was on another SO question here : Query on [Python sum of number in array, ignoring sections of specific numbers]

In this question, there was a code similar to this :

it = iter([4, 5, 6, 7, 8, 9])
print([x for x in it if x!=4 not in it]) #Output [5]

To my understanding, an iterator is like a list in which we remove each element after accessing them. I also get that making an operation like not in will loop over the iterator until it find the value it's searching for. So in the case where we do 3 not in iter([1, 2]) the iterator will be empty since the not in have looped over all of it to confirm that 3 wasn't included.

So in my understanding, the first iteration of the for loop should do the following :

it = iter([4, 5, 6, 7, 8, 9])
for x in it:
    #Here it look like [5, 6, 7, 8, 9] and x is 4
    if x!=4 not in it:
        # So here we've done 
        #x!=4 => False 
        #then False not in it
        #Since False isn't in it the iterator should now be empty and we don't enter this if
        print(x)

#And there is'nt a second iteration since the iterator is empty dues to the if condition so
#the loop should end after the first iteration without anything printed

But this code output is 5 how on earth is this possible ???
So if someone can explain in details what is happening exactly it would be greatly appreciated !

Side notes :
I've also tried with

  • (x!=4) not in it ⇾ output is 4
  • x!=(4 not in it) ⇾ output nothing

Which make me wonder how is this condition interpreted by python, since none of the parenthesized versions match the version without parenthesis.

5
  • I'm well aware of this and that's the point of the question of why does it still print something when it should be exhausted. Commented Apr 28, 2022 at 19:38
  • 1
    #Since False isn't in it the iterator should now be empty and we don't enter this if - I think this is where the confusion is. Since False isn't in the iterator, you will enter the if, because the condition checks for not in. Commented Apr 28, 2022 at 19:41
  • @TimRoberts No it didn't find 4 with the not in since it's already removed by the for loop who put it in x. for x in it: \n print(4 in it) This output false. Commented Apr 28, 2022 at 19:43
  • 2
    No, the issue here is comparison operator chaining. Commented Apr 28, 2022 at 19:44
  • 1
    @0x5453 I agree with this, but in this case the code should be printing 4 not 5 Commented Apr 28, 2022 at 19:46

1 Answer 1

4

So, the problem here is the expression:

x != 4 not in it

Is implicitly chained, because that is how comparison operators work

So that means it is evaluated as:

(x != 4) and (4 not in it)

Since x != 4 is False on the first iteration, it short circuits and goes on to the next iteration without evaluating 4 in it. In which case, x == 5, and it doesn't short circuit and it exhausts the iterator checking if 5 not in it, in which case, the whole expression is True and it is the only item in the resulting list.

Sign up to request clarification or add additional context in comments.

2 Comments

Great spotting. This is the same "feature" that allows "3 < x < 7" to work.
A big thanks ! This seriously got me to go crazy for the big part of my afternoon.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.