John Doe John Doe - 5 months ago 22
Python Question

How does the "in" and "not in" statement work in python

I studied predominantly in C and spent a lot of time understanding its implementation under the hood. But I've recently begun learning python. So there are a lot of quirks here different from C.

How does the 'in' statement work in python?

if x in array:
#the usage of an in statement produces a boolean
for x in array:
#the usage of an in statement produces an iterable

Also as a side question. 'Not' can be placed in front of a boolean expression, similar to '!' in C or it can be placed in front of the 'in' statement in python. How is this possible?

if not x == 5:
#makes sense because 'x == 5' evaluates to a boolean
if x not in array:
#the statement 'in array' is not a boolean
#shouldn't it be 'if not x in array'

How are both of these possible? Shouldn't there be a consistency in how they are evaluated? Right now, I believe that it's because Python is an interpreted language, the interpreter can just do different things based on the surrounding syntax.

An explanation or link to an explanation would be super helpful, I've been unable to find anything addressing this.

Answer Source

You are confusing two totally unrelated pieces of syntax.

One is a statement, see the for statement documentation. The in is part of the fixed grammar:

for_stmt ::=  “for” target_list “in” expression_list “:” suite
              [“else” “:” suite]

The moment you use for to start a line, the in part is required, just as the : is required. And don't confuse Python's for with a C for loop; Python's is a For Each construct. As such it doesn't 'produce' an iterable, it requires an iterable as input.

The other is a membership test operation, and operators are a type of expression:

The operators in and not in test for membership.

It is meant to apply to containers (not just iterables).

Both are leaning heavily on Python's OO nature, something C can't do. If you want to find equivalents in other languages, look at concepts in C++, Java or C#, not at C.

for <expr> in <iterable> takes an iterable object, something that can produce elements, one after another. C++ has an equivalent concept, in Java there are parallels in iterators and streams.

<expr> [not] in <expr> only requires that the right-hand expression result supports membership testing, but Python will fall back to iteration if no explicit hooks are available for a membership test. The not in not in simply inverts the result of the in operation.

C++ and Java have no standard abstraction for this, different container types each implement their own spelling (in C++ most call it find, e.g. set::find or map::find, while Java usually picks contains variations, giving you Set.contains(), and Map.containsKey()).