Reputation: 669
If I understand properly, we in Python we have:
__iter__()
is implemented__iter__()
returns self & __next__()
is implementedyield
statement or a generator expression.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
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