On Fri, May 15, 2020 at 1:19 PM Stephen J. Turnbull turnbull.stephen.fw@u.tsukuba.ac.jp wrote:
ISTM that all we need to say is that
An *iterator* is a Python object whose only necessary function is to return an object when next is applied to it. Its purpose is to keep track of "next" for *for*. (It might do other useful things for the user, eg, file objects.)
The *for* statement and the *next* builtin require an iterator object to work. Since for *always* needs an iterator object, it automatically converts the "in" object to an iterator implicitly. (Technical note: for the convenience of implementors of 'for', when iter is applied to an iterator, it always returns the iterator itself.)
That's not a mere technical detail - that's actually part of the definition of an iterator, namely that iter(x) is x. That's how you can tell that it's an iterator.
Objects that can be converted to iterators are *iterables*. Trivially, iterators are iterable (see technical note supra).
Most Python objects are not iterators, but many can be converted. However, some Python objects are constructed as iterators because they want to be "lazy". Examples are files (so that a huge file can be processed line by line without reading the whole thing into memory) and "generators" which yield a new item each time they are called.
I don't like this term "converted". It's very frequently used to describe the construction of an integer based on the digits in a string, for instance, and in that case it's at least useful, but it's never really correct. There's nothing being converted anywhere. Getting an iterator from an iterable isn't converting anything.
(Part of the reason I don't like int(txt) to be called a conversion is that it sounds like a mutation operation. If you have a variable that currently contains "1234", calling int(x) is not going to change what that variable contains. Seen way too many students get this wrong.)
ChrisA