开发者

def next() for Python pre-2.6? (instead of object.next method)

Python 2.6+ and 3.* have next(), but pre-2.6 only offers the object.next method. Is there a way to get the next() style in pre-2.6; some "def next():" construction开发者_如何转开发 perhaps?


class Throw(object): pass
throw = Throw() # easy sentinel hack
def next(iterator, default=throw):
  """next(iterator[, default])

  Return the next item from the iterator. If default is given
  and the iterator is exhausted, it is returned instead of
  raising StopIteration.
  """
  try:
    iternext = iterator.next.__call__
    # this way an AttributeError while executing next() isn't hidden
    # (2.6 does this too)
  except AttributeError:
    raise TypeError("%s object is not an iterator" % type(iterator).__name__)
  try:
    return iternext()
  except StopIteration:
    if default is throw:
      raise
    return default

(throw = object() works too, but this generates better docs when inspecting, e.g. help(next). None is not suitable, because you must treat next(it) and next(it, None) differently.)


R. Pate seems to have a good answer. One extra bell to add: if you're writing code to run on many different versions of Python, you can conditionalize the definition:

try:
    next = next
except NameError:
    def next():
        # blah blah etc

That way you have next defined in any case, but you're using the built in implementation where it's available.

I use next = next so that I can put this definition in a module, then elsewhere in my code use:

from backward import next


Simpler method:

import operator

next = operator.methodcaller("next")

Ned's suggestion about putting it in a try block works here as well, but if you're going to go that route, one minor note: in Python 3, calling next() on a non-iterator raises a TypeError, whereas this version would raise an AttributeError instead.

Edit: Never mind. As steveha points out, operator.methodcaller() was only introduced in 2.6, which is a shame.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜