Sequence iterators with __index__

Terry Reedy tjreedy at udel.edu
Tue Jun 24 20:46:03 EDT 2008



schickb wrote:
> On Jun 24, 3:45 pm, Matimus <mccre... at gmail.com> wrote:
>>> I think it would be useful if iterators on sequences had the __index__
>>> method so that they could be used to slice sequences. I was writing a
>>> class and wanted to return a list iterator to callers.  I then wanted
>>> to let callers slice from an iterator's position, but that isn't
>>> supported without creating a custom iterator class.

Creating custom classes is what the class statement is for.  See below.

>> Could you post an example of what you are talking about? I'm not
>> getting it.
> 
> Interactive mock-up:
> 
>>>> a = ['x','y','z']
>>>> it = iter(a)
>>>> a[it:]
> ['x', 'y', 'z']
>>>> it.next()
> 'x'
>>>> a[it:]
> ['y', 'z']
>>>> a[:it]
> ['x']
>>>> it.next()
> 'y'
>>>> a[it:]
> ['z']
> 
> This lets you use sequence iterators more general position indicators.
> Currently if you want to track a position and slice from a tracked
> position you must do it manually with an integer index. It's not
> difficult, but given that sequence iterators already do that already
> it seems redundant (and of course more error prone).

Python's iterator protocol is intentionally simple and general.
Wanting to slice while iterating is a *very* specialized usage.
In any case:
A. If the iterator uses in incrementing index to iterate, you want access.
B. Using an iterator as an integer will strike most people as 
conceptually bizarre; it will never be accepted.
C. Doing so is unnecessary since the internal index can just as easily 
be exposed as an integer attribute called 'index' or, more generally, 
'count'.
a[it.count:] looks *much* better.
D. You can easily add .index or .count to any iterator you write.  The 
iterator protocol is a minimum rather than maximum specification.
E. You can easily wrap any iterable/iterator in an iterator class that 
provides .count for *any* iteration process.  Slicing is not the only 
possible use of such an attribute.

class indexerator():
   def __inti__(self, iterable):
     self.it = iter(iterable)
     self.count = 0
   def __iter__(self): return self
   def __next__(self): # 3.0
     tem = self.it.next()
     self.count += 1
     return tem

.count is always the number of items returned.  It is also the index of 
the next item to be returned if (but only if() the base iterable exists 
and is an indexable sequence.
F. Even this should be unnecessary for most usages.  Built-in function 
enumerate(iterable) generates count,item pairs in much the same manner:

>> In any case, the first step is writing a PEP.http://www.python.org/dev/peps/

Discussion usually comes first.

> Ok thanks, but I do want some idea of interest level before spending a
> bunch of time on this.

Even the developers sometimes take this precaution.  Many ideas never 
make it to the PEP stage.  I see no need for a change in Python here.

Terry Jan Reedy




More information about the Python-list mailing list