Jeffery
Jeffery

Reputation: 669

Which Python iterables are consumable?

If I understand properly, we in Python we have:

Question: Are there categories above that are always/never consumable?

By consumable I mean iterating through them "destroys" the iterable; like zip() (consumable) vs range() (not consumable).

Upvotes: 1

Views: 362

Answers (1)

chepner
chepner

Reputation: 531718

All iterators are consumed; the reason you might not think so is that when you use an iterable with something like

for x in [1,2,3]:

the for loop is creating a new iterator for you behind the scenes. In fact, a list is not an iterator; iter([1,2,3]) returns something of type list_iterator, not the list itself.


Regarding the example you linked to in a comment, instead of

class PowTwo:    
    def __init__(self, max=0):
        self.max = max

    def __iter__(self):
        self.n = 0
        return self

    def __next__(self):
        if self.n <= self.max:
            result = 2 ** self.n
            self.n += 1
            return result
        else:
            raise StopIteration

which has the side effect of modifying the iterator in the act of returning it, I would do something like

class PowTwoIterator:    
    def __init__(self, max=0):
        self.max = max
        self._restart()

    def _restart(self):
        self._n = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self._n <= self.max:
            result = 2 ** self._n
            self._n += 1
            return result
        else:
            raise StopIteration

Now, the only way you can modify the state of the object is to do so explicitly (and even that should not be done lightly, since both _n and _restart are marked as not being part of the public interface).

The change in the name reminds you that this is first and foremost an iterator, not an iterable that can provide independent iterators from.

Upvotes: 2

Related Questions