Quoting Perfomance Tips:
xrange
is a generator object, basically equivalent to the following
Python 2.3 code:
def xrange(start, stop=None, step=1):
if stop is None:
stop = start
start = 0
else:
stop = int(stop)
start = int(start)
step = int(step)
while start < stop:
yield start
start += step
Except that it is implemented in pure C.
They say that in
is inefficient on xrange
objects because in
tries to iterate over object if the __contains__
approach failed. From Membership test details:
For classes which do not define __contains__()
but do define
__iter__()
, x in y
is true if some value z
with x == z
is
produced while iterating over y
.
xrange
does not implement __contains__
and in order to "find" element N in xrange(N + 1)
in
operator has to perform N iterations so
N in xrange(N + 1)
is logically equivalent to
for n in xrange(N + 1):
if n == N:
break
and it's not efficient.
not in
is inefficient because in
is inefficient.
Note that performance of in
operator for containment tests doesn't affect the performance of the for
loop. These are 2 different things.
In fact, the "in"
in the grammar rule for the for
loop (shown below)
for_stmt ::= "for" target_list "in" expression_list ":" suite
["else" ":" suite]
is fixed and is not an operator.