5

Python 2.6+ 和 3.* 有 next(),但 pre-2.6 只提供 object.next 方法。有没有办法在 pre-2.6 中获得 next() 样式;也许是一些“def next():”构造?

4

3 回答 3

11
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()也可以,但这会在检查时生成更好的文档,例如help(next).None不适合,因为您必须区别对待next(it)next(it, None)

于 2009-11-11T16:39:56.267 回答
6

R. Pate 似乎有一个很好的答案。一个额外的补充:如果您正在编写代码以在许多不同版本的 Python 上运行,您可以对定义进行条件化:

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

这样你next在任何情况下都已经定义了,但是你使用的是可用的内置实现。

我使用next = next以便我可以将此定义放在一个模块中,然后在我的代码中的其他地方使用:

from backward import next
于 2009-11-11T16:43:42.240 回答
2

更简单的方法:

import operator

next = operator.methodcaller("next")

Ned 关于将它放在一个try块中的建议在这里也有效,但如果你要走那条路,一个小注意事项:在 Python 3 中,调用next()非迭代器会引发 a TypeError,而这个版本会引发 an AttributeError

编辑:没关系。正如 steveha 指出的那样,operator.methodcaller()仅在 2.6 中引入,这是一种耻辱。

于 2009-11-11T19:28:02.097 回答