[Python-Dev] itertools addition: getitem()

Walter Dörwald walter at livinglogic.de
Mon Jul 9 08:16:35 CEST 2007


Raymond Hettinger wrote:
> [Walter Dörwald]
>> I'd like to propose the following addition to itertools: A function
>> itertools.getitem() which is basically equivalent to the following
>> python code:
>>
>> _default = object()
>>
>> def getitem(iterable, index, default=_default):
>>    try:
>>       return list(iterable)[index]
>>    except IndexError:
>>       if default is _default:
>>          raise
>>       return default
>>
>> but without materializing the complete list. Negative indexes are
>> supported too (this requires additional temporary storage for abs(index)
>> objects).
> 
> Why not use the existing islice() function?
> 
>   x = list(islice(iterable, i, i+1)) or default

This doesn't work, because it produces a list

>>> list(islice(xrange(10), 2, 3)) or 42
[2]

The following would work:
   x = (list(islice(iterable, i, i+1)) or [default])[0]

However islice() doesn't support negative indexes, getitem() does.

> Also, as a practical matter, I think it is a bad idea to introduce
> __getitem__ style access to itertools because the starting point
> moves with each consecutive access:
> 
>    # access items 0, 2, 5, 9, 14, 20, ...
>    for i in range(10):
>        print getitem(iterable, i)
> 
> Worse, this behavior changes depending on whether the iterable
> is re-iterable (a string would yield consecutive items while a
> generator would skip around as shown above).

islice() has the same "problem":

>>> from itertools import *
>>> iterable = iter(xrange(100))
>>> for i in range(10):
...     print list(islice(iterable, i, i+1))
[0]
[2]
[5]
[9]
[14]
[20]
[27]
[35]
[44]
[54]

>>> iterable = xrange(100)
>>> for i in range(10):
...     print list(islice(iterable, i, i+1))
[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]

> Besides being a bug factory, I think the getitem proposal would
> tend to steer people down the wrong road, away from more
> natural solutions to problems involving iterators.

I don't think that
   (list(islice(iterable, i, i+1)) or [default])[0]
is more natural than
   getitem(iterable, i, default)

> A basic step
> in learning the language is to differentiate between sequences
> and general iterators -- we should not conflate the two.

Servus,
   Walter


More information about the Python-Dev mailing list