Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subscripting itertools.repeat

Given that range objects were made subscriptable, why aren't itertools.repeat objects subscriptable?

In [10]: range(3, 10)[3]
Out[10]: 6

In [11]: import itertools as it

In [12]: it.repeat(5)[3]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-12-1ef74480e0a7> in <module>()
----> 1 it.repeat(5)[3]

TypeError: 'itertools.repeat' object is not subscriptable

Note that range objects and itertools.repeat objects are part of Python 3.

I would prefer:

class repeat_(itertools.repeat):
    def __init__(self, object_, times=None):
        super().__init__(object_, times)

        self.object_ = object_
        self.times = times

    def __reversed__(self):
        return self

    def __getitem__(self, key):
        return self.object_

    def __contains__(self, key):
        return key == self.object_

    def __len__(self):
        if self.times is None:
            raise ValueError
        return self.times
like image 332
Neil G Avatar asked Jun 11 '26 00:06

Neil G


1 Answers

repeat just yields the same object over and over again. I'm not really sure what subscripting it would actually do for you ... You would be just as well to call next(repeat_object). Perhaps you are thinking about cycle (as I did when I originally read your question)?

Part the the wonder of itertools is that it attempts to operate as lazily as it possibly can. In light of this, what do you expect to happen if you pass a generator expression to itertools.cycle? cycle has NO WAY to know the length of the object you passed in short of casting the whole thing to a tuple and inquiring. Doing that would probably break the API in a bunch of other places (now you consume your iterable when you subscript your repeat object) or it would take a whole lot more intermediate storage via an unnecessary itertools.tee -- which is what itertools tries to avoid. As it is currently implemented, cycle on a huge generator expression that you can't hope to hold in memory works (as long as you don't actually iterate over all the elements), but that wouldn't be the case if you tried to subscript it at a large index.

Finally, as the name implies, itertools is a library for creating iterable objects. As such, there is no reason to expect that the objects are subscriptable. (It's not called subscripttools after all :).

As a side note, you might be able to do what you want with itertools.islice.

like image 161
mgilson Avatar answered Jun 13 '26 16:06

mgilson