hasNext in Python iterators? hasNext in Python iterators? python python

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