On Sun, Aug 9, 2015 at 7:06 PM, Pierre Quentel <pierre.quen...@gmail.com> wrote: > "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." > > ... > 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.
That's exactly right. The only way for the interpreter to handle 'in' on an iterator is something like this: def contains(iter, obj): for val in iter: if val == obj: return True return False That's what the docs describe. So what you have is something like this: for i in iterator: for j in iterator: if i == j: break else: assert False, '%s not found' %i You're dragging values from the same iterator, so you're consuming it as part of your membership test. You can do this kind of thing: >>> 5 in A(10) True but if you've already consumed a few values, those won't be in the iterator any more: >>> x = A(10) >>> next(x) 0 >>> next(x) 1 >>> next(x) 2 >>> next(x) 3 >>> 2 in x False This is simply how iterators work. They're very different from repeatable iterables like lists or range objects, where you _can_ test for membership that way: >>> x = [10,20,30] >>> for i in x: assert i in x ... >>> x = iter([10,20,30]) >>> for i in x: assert i in x ... Traceback (most recent call last): File "<stdin>", line 1, in <module> AssertionError Note that I _could_ create a list that would pass this assertion, simply by duplicating every value: >>> x = iter([10,10,20,20,30,30]) >>> for i in x: assert i in x ... But it's iterating only three times here, and the 'in' check is consuming the other three values. Once your A(10) has yielded some value, it will never yield it again, so the assertion can never pass. Does that explain matters? ChrisA -- https://mail.python.org/mailman/listinfo/python-list