hasNext in Python iterators?
There's an alternative to the StopIteration
by using next(iterator, default_value)
.
For exapmle:
>>> a = iter('hi')>>> print next(a, None)h>>> print next(a, None)i>>> print next(a, None)None
So you can detect for None
or other pre-specified value for end of the iterator if you don't want the exception way.
No, there is no such method. The end of iteration is indicated by an exception. See the documentation.
If you really need a has-next
functionality, it's easy to obtain it with a little wrapper class. For example:
class hn_wrapper(object): def __init__(self, it): self.it = iter(it) self._hasnext = None def __iter__(self): return self def next(self): if self._hasnext: result = self._thenext else: result = next(self.it) self._hasnext = None return result def hasnext(self): if self._hasnext is None: try: self._thenext = next(self.it) except StopIteration: self._hasnext = False else: self._hasnext = True return self._hasnext
now something like
x = hn_wrapper('ciao')while x.hasnext(): print next(x)
emits
ciao
as required.
Note that the use of next(sel.it)
as a built-in requires Python 2.6 or better; if you're using an older version of Python, use self.it.next()
instead (and similarly for next(x)
in the example usage). [[You might reasonably think this note is redundant, since Python 2.6 has been around for over a year now -- but more often than not when I use Python 2.6 features in a response, some commenter or other feels duty-bound to point out that they are 2.6 features, thus I'm trying to forestall such comments for once;-)]]
===
For Python3, you would make the following changes:
from collections.abc import Iterator # since python 3.3 Iterator is hereclass hn_wrapper(Iterator): # need to subclass Iterator rather than object def __init__(self, it): self.it = iter(it) self._hasnext = None def __iter__(self): return self def __next__(self): # __next__ vs next in python 2 if self._hasnext: result = self._thenext else: result = next(self.it) self._hasnext = None return result def hasnext(self): if self._hasnext is None: try: self._thenext = next(self.it) except StopIteration: self._hasnext = False else: self._hasnext = True return self._hasnext