Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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.

like image 550
John Doe Avatar asked Aug 16 '17 07:08

John Doe


2 Answers

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()).

like image 53
Martijn Pieters Avatar answered Oct 26 '22 01:10

Martijn Pieters


The for x in array: is not much different from the range based for loop introduced in c++11. The syntax in c++ is also quite similar:

int a[] = {0, 1, 2, 3, 4, 5};
for (int n : a) // the initializer may be an array
    std::cout << n << ' ';

The statements if x in a: and for x in a: do not have much to do with each other, they simply feature the same word in, but it has different meaning.

You could easily imagine how one would implement a feature similar to if x in a: in c++ - for instance use std::find. An alternative is to iterate over the container and compare each element to x. There can be specific overloads for certain types of containers to make this more performant of course, but important thing is that it can be implemented.

like image 26
Ivaylo Strandjev Avatar answered Oct 26 '22 01:10

Ivaylo Strandjev