Iterators membership testing

Pierre Quentel pierre.quentel at gmail.com
Sun Aug 9 11:06:50 CEST 2015


The documentation at https://docs.python.org/3.5/reference/expressions.html#not-in says :

"For user-defined 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. If an exception is raised during the iteration, it is as if 
in raised that exception."

However, if I define a class with

class A:
    
    def __init__(self, x):
        self.x = x
        self.counter = -1
    
    def __iter__(self):
        return self
    
    def __next__(self):
        self.counter += 1
        if self.counter >= self.x:
            raise StopIteration
        return self.counter

and test for membership with

iterator = A(10)

for i in iterator:
    assert i in iterator, '%s not found' %i

I get an assertion error. Setting a trace on __next__ suggests that for 
membership testing, the interpreter consumes the iterator until the searched 
value is found (or until exhaustion), then it resumes iteration at this point.
For instance :

>>> iterator = A(10)
>>> for i in iterator:
...  print(i)
...  assert i+1 in iterator
...
0
2
4
6
8
>>>

If this is correct, should the documentation mention it ?


More information about the Python-list mailing list