views:

762

answers:

8

Haven't Python iterators got a hasNext method?

+3  A: 

No. The most similar concept is most likely a StopIteration exception.

James Thompson
What Python uses exceptions for control flow ? Sounds pretty nafted.
mP
+1  A: 

I believe python just has next() and according to the doc, it throws an exception is there are no more elements.

http://docs.python.org/library/stdtypes.html#iterator-types

Charles
+8  A: 

No, there is no such method. The end of iteration is indicated by an exception. See the documentation.

avakar
"It's easier to ask for forgiveness than permission."
Roger Pate
+2  A: 

hasNext somewhat translates to the StopIteration exception, e.g.:

>>> it = iter("hello")
>>> it.next()
'h'
>>> it.next()
'e'
>>> it.next()
'l'
>>> it.next()
'l'
>>> it.next()
'o'
>>> it.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
The MYYN
+6  A: 

If you really need a has-next functionality (because you're just faithfully transcribing an algorithm from a reference implementation in Java, say, or because you're writing a prototype that will need to be easily transcribed to Java when it's finished), 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

c
i
a
o

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;-)]]

Alex Martelli
+1  A: 

In addition to all the mentions of StopIteration, the Python "for" loop simply does what you want:

>>> it = iter("hello")
>>> for i in it:
...     print i
...
h
e
l
l
o
Brian Clapper
A: 

You can tee the iterator using, itertools.tee, and check for StopIteration on the teed iterator.

sykora
A: 

Try the __length_hint__() method from any iterator object:

iter(...).__length_hint__() > 0
juj
I always wondered why on earth python has all those __ xxx __ methods ? They seem so ugly.
mP