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