[Python-ideas] Integrate some itertools into the Python syntax

Terry Reedy tjreedy at udel.edu
Mon Mar 28 17:46:27 EDT 2016


On 3/27/2016 11:26 PM, Chris Barker - NOAA Federal wrote:

> But range used to produce a list.  So for lips were, in the beginning,
> about iterating, yes, but iterating through a sequence, not an
> arbitrary iterables. I may be wrong here, but I started using Python
> in version 1.5, and I'm pretty sure the iterator protocol did not
> exist then -- I know for sure I learned about it far later.

The current iterator protocol, based on __iter__, __next__, and 
StopIteration, was added in 2.2.  The original iteration protocol, now 
called the 'sequence protocol', was based on __getitem__(count) and 
IndexError.  Except for not requiring a __length__ method, it required 
that what we now call an 'iterable' pretend to be a sequence.  It is 
still supported by iter().
https://docs.python.org/3/library/functions.html#iter

With the additional changes to builtins in 3.0, there has definitely 
been a shift of emphasis from lists and sequences to iterables and 
iterators.
---

General response to thread: In spite of this, I am not in favor of 
trying to force-fit itertools, in particular islice, into syntax. 
Iterables for which slicing makes sense are free to directly support 
non-destructive slicing in a __getitem__ method.  It does not bother me 
that destructive slicing of iterators requires a different syntax.

Because of the difference between non-destructive and destructive 
slicing, the goal of making the same code work for sequences and 
iterators cannot work beyond a single slice.  Suppose one wants to 
process the first 5 and then the next 5 items of an iterable.  The 
necessary code is different for sequences and iterators.

from itertools import islice

rs = range(10)
ri = iter(rs)

print(list(islice(rs, 0, 5)))
print(list(islice(rs, 0, 5)))
print()
print(list(islice(ri, 0, 5)))
print(list(islice(ri, 0, 5)))  # works for iterators
print()

ri = iter(rs)

print(list(islice(rs, 0, 5)))
print(list(islice(rs, 5, 10)))  # works for sequences
print()
print(list(islice(ri, 0, 5)))
print(list(islice(ri, 5, 10)))

#
[0, 1, 2, 3, 4]
[0, 1, 2, 3, 4]

[0, 1, 2, 3, 4]
[5, 6, 7, 8, 9]

[0, 1, 2, 3, 4]
[5, 6, 7, 8, 9]

[0, 1, 2, 3, 4]
[]

How anyone written and experimented with using a 'syntax-iterator' class 
to test the idea?  Has such to uploaded to PyPI?

import itertools

class Iter:  # syntax-intergrated iterator
     def __init__(self, iterable):
         self.it = iter(iterable)
     def __iter__(self):
         return self
     def __next__(self):
         return next(self.it)
     def __getitem__(self, what):
         if isistance(what, slice):
             return itertools.islice(
                     what.start or 0, what.stop, what.step or 1)
     def __add__(self, other):
         return itertools.chain(self, other)
# for more that two iterables, chain(a, b, c, ...) will run faster
     ...

Then, in the current idiom for a function of an iterable:

def f(args, iterable, args):
     it = iter(iterable)

one could replace 'iter' with 'Iter' and proceed to use proposed 
iterator syntax within the function.

-- 
Terry Jan Reedy



More information about the Python-ideas mailing list