[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Iterators, iterables and special objects

On 7/23/2020 5:14 AM, Peter Sl??ik wrote:
>> Works in what way? You can't use it in a 'for' loop if it doesn't
>> define __iter__.
> class Iterable:
>      def __iter__(self):
>          return Iterator(...)
> class Iterator:
>      def __next__(self):
>          return <next item>
>      # No __iter__ here.
>      # I've just forgotten to def it.

Which means that an Iterator is not an iterator.

> With this setup, using for to iterate over Iterable *will* still work,
> though you cannot use the trick described below.
>> Yes? It is indeed an iterator, since its iter method returns itself. It
> is also iterable, since it has an iter method.
> Of course, you're right. But you're reading the article through the eyes of
> an experienced developer.
>> It's so you can do things like this:
>> def show_with_header(stuff):
>>      stuff = iter(stuff)
>>      hdr = next(stuff)
>>      print(hdr)
>>      for line in stuff:
>>          print(line)
>>          if new_page(): print(hdr)
> Yes, @Terry had given the same example. Frankly, I didn't know about it
> before, I somehow had the misconception that for always got a 'fresh'
> iterator...

The way 'for' gets its iterator is to call iter(iterable).  If the 
iterable is an iterator, iter(iterator) returns iterator.  Open files 
are *iterators*.

 >>> file.__iter__() is file

This means that one can do things like

file  = open(...)
for line in file:  # Section 1 of file.
     if separator(line): break
process_sep(line)  # Special line that broke iteration.
for line in file:  # Section 2 of file.

One alternative is something like

file = open(...)
section = 1
for line in file:
     if section == 1:
	if separator(line):
             section = 2

Another is to use while loops and explicit next(line) calls.  The ':=' 
assignment operator makes this a bit easier.  I used to commonly process 
files with multiple sections and different 'key' lines marking them.

Terry Jan Reedy