[Python-Dev] Re: Should the definition of an "(async) iterator" include __iter__?

2021年9月14日 23:41:11 -0700

On Tue, Sep 14, 2021 at 09:38:38PM -0700, Guido van Rossum wrote:
> > I don't know what I would call an object that only has __next__,
> > apart from "broken" :-(
> >
> 
> It's still an iterator, since it duck-types in most cases where an iterator
> is required (notably "for", which is the primary use case for the iteration
> protocols -- it's in the first sentence of PEP 234's abstract).
I don't think it duck-types as an iterator. Here's an example:
class A:
 def __init__(self): self.items = [1, 2, 3]
 def __next__(self):
 try: return self.items.pop()
 except IndexError: raise StopIteration
 
class B:
 def __iter__(self):
 return A()
It's fine to iterate over B() directly, but you can't iterate over 
A() at all. If you try, you get a TypeError:
 >>> for item in A(): pass
 ... 
 Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 TypeError: 'A' object is not iterable
In practice, this impacts some very common techniques. For instance, 
pre-calling iter() on your input.
 >>> x = B()
 >>> it = iter(x)
 >>> for value in it: pass
 ... 
 Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 TypeError: 'A' object is not iterable
There are all sorts of reasons why one might pre-call iter(). One common 
one is to pre-process the first element:
 it = iter(obj)
 first = next(obj, None)
 for item in it: ...
Another is to test for an iterable. iter(obj) will raise TypeError if 
obj is not a sequence, collection, iterator, iterable etc.
Another is to break out of one loop and then run another:
 it = iter(obj)
 for x in it:
 if condition: break
 do_something()
 for x in it:
 something_else()
I'm sure there are others I haven't thought of.
I believe that iterable objects that define `__next__` but not 
`__iter__` are fundamentally broken. If they happen to work in some 
circumstances but not others, that's because the iterator protocol is 
relaxed enough to work with broken iterators :-)
-- 
Steve
_______________________________________________
Python-Dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/[email protected]/message/54WUEDKDIT7FXH3JHL34VZDJCFV5Q3FH/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to