[Python-Dev] Single- vs. Multi-pass iterability
Guido van Rossum
guido@python.org
2002年7月17日 17:21:26 -0400
> __iter__ is a red herring. It has nothing to do with the act of
> iterating. It exists only to support the use of "for" directly
> on the iterator. Iterators that currently implement "next" but
> not "__iter__" will work in some places and not others. For
> example, given this:
>> class Counter:
> def __init__(self, last):
> self.i = 0
> self.last = last
>> def next(self):
> self.i += 1
> if self.i > self.last: raise StopIteration
> return self.i
>> class Container:
> def __init__(self, size):
> self.size = size
>> def __iter__(self):
> return Counter(self.size)
>> This will work:
>> >>> for x in Container(3): print x
> ...
> 1
> 2
> 3
>> But this will fail:
>> >>> for x in Counter(3): print x
> ...
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> TypeError: iteration over non-sequence
>> It's more accurate to say that there are two distinct protocols here.
>> 1. An object is "for-able" if it implements __iter__ or __getitem__.
> This is a subset of the sequence protocol.
>> 2. An object can be iterated if it implements next.
>> The Container supports only protocol 1, and the Counter supports
> only protocol 2, with the above results.
>> Iterators are currently asked to support both protocols. The
> semantics of iteration come only from protocol 2; protocol 1 is
> an effort to make iterators look sorta like sequences. But the
> analogy is very weak -- these are "sequences" that destroy
> themselves while you look at them -- not like any typical
> sequence i've ever seen!
>> The short of it is that whenever any Python programmer says
> "for x in y", he or she had better be darned sure of whether
> this is going to destroy y. Whatever we can do to make this
> clear would be a good idea.
This is a very good summary of the two iterator protocols. Ping,
would you mind adding this to PEP 234?
--Guido van Rossum (home page: http://www.python.org/~guido/)