"x not in" vs. "not x in"

PythonOperators

Python Problem Overview


I've noticed that both of these work the same:

if x not in list and if not x in list.

Is there some sort of difference between the two in certain cases? Is there a reason for having both, or is it just because it's more natural for some people to write one or the other?

Which one am I more likely to see in other people's code?

Python Solutions


Solution 1 - Python

The two forms make identical bytecode, as you can clearly verify:

>>> import dis
>>> dis.dis(compile('if x not in d: pass', '', 'exec'))
  1           0 LOAD_NAME                0 (x)
              3 LOAD_NAME                1 (d)
              6 COMPARE_OP               7 (not in)
              9 JUMP_IF_FALSE            4 (to 16)
             12 POP_TOP             
             13 JUMP_FORWARD             1 (to 17)
        >>   16 POP_TOP             
        >>   17 LOAD_CONST               0 (None)
             20 RETURN_VALUE        
>>> dis.dis(compile('if not x in d: pass', '', 'exec'))
  1           0 LOAD_NAME                0 (x)
              3 LOAD_NAME                1 (d)
              6 COMPARE_OP               7 (not in)
              9 JUMP_IF_FALSE            4 (to 16)
             12 POP_TOP             
             13 JUMP_FORWARD             1 (to 17)
        >>   16 POP_TOP             
        >>   17 LOAD_CONST               0 (None)
             20 RETURN_VALUE        

so obviously they're semantically identical.

As a matter of style, PEP 8 does not mention the issue.

Personally, I strongly prefer the if x not in y form -- that makes it immediately clear that not in is a single operator, and "reads like English". if not x in y may mislead some readers into thinking it means if (not x) in y, reads a bit less like English, and has absolutely no compensating advantages.

Solution 2 - Python

>>> dis.dis(lambda: a not in b)
1           0 LOAD_GLOBAL              0 (a)
          3 LOAD_GLOBAL              1 (b)
          6 COMPARE_OP               7 (not in)
          9 RETURN_VALUE      

>>> dis.dis(lambda: not a in b)
1           0 LOAD_GLOBAL              0 (a)
          3 LOAD_GLOBAL              1 (b)
          6 COMPARE_OP               7 (not in)
          9 RETURN_VALUE  


when you do "not a in b" it will need be converted for (not in)

so, the right way is "a not in b".

Solution 3 - Python

not x in L isn't explicitly disallowed because that would be silly. x not in L is explicitly allowed (though it compiles to the same bytecode) because it's more readable.

x not in L is what everyone uses, though.

Solution 4 - Python

When you write a not in b it is using the not in operator, whereas not a in b uses the in operator and then negates the result. But the not in operator is defined to return the same as not a in b so they do exactly the same thing. From the documentation:

> The operators in and not in test for collection membership. x in s evaluates to true if x is a member of the collection s, and false otherwise. x not in s returns the negation of x in s.

Similarly there is a is not b versus not a is b.

The extra syntax was added because it makes it easier for a human to read it naturally.

Solution 5 - Python

It just personal preference. You could also compare if x != 3 and if not x == 3. There's no difference between the two expressions you've shown.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionavacariuView Question on Stackoverflow
Solution 1 - PythonAlex MartelliView Answer on Stackoverflow
Solution 2 - PythonkillownView Answer on Stackoverflow
Solution 3 - PythonhabnabitView Answer on Stackoverflow
Solution 4 - PythonMark ByersView Answer on Stackoverflow
Solution 5 - PythonNed BatchelderView Answer on Stackoverflow