简体   繁体   中英

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

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 .

itertool.repeat() method returns an iterator, not a list, as is the case with range function. So, you can't subscript on it.

Here's what documentation says: -

Make an iterator that returns object over and over again. Runs indefinitely unless the times argument is specified.

From documentation of range : -

If you do need to iterate over a sequence of numbers, the built-in function range() comes in handy. It generates lists containing arithmetic progressions


In Python 3 , difference is that, range() creates a Generator object. Which xrange function in Python 2 did.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM