def next () для Python до 2.6? (вместо метода object.next) - PullRequest
5 голосов
/ 11 ноября 2009

Python 2.6+ и 3. * имеют next (), но pre-2.6 предлагает только метод object.next. Есть ли способ получить стиль next () в pre-2.6; какая-нибудь конструкция "def next ():" возможно?

Ответы [ 3 ]

11 голосов
/ 11 ноября 2009
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) по-разному.)

6 голосов
/ 11 ноября 2009

R. Пэйт, кажется, имеет хороший ответ. Еще один колокольчик, который нужно добавить: если вы пишете код для запуска на многих различных версиях Python, вы можете обусловить определение:

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

Таким образом, вы в любом случае определяете next, но вы используете встроенную реализацию там, где она доступна.

Я использую next = next, чтобы я мог поместить это определение в модуль, а затем в другое место моего кода использовать:

from backward import next
2 голосов
/ 11 ноября 2009

Более простой метод:

import operator

next = operator.methodcaller("next")

Предложение Неда о размещении его в блоке try работает и здесь, но если вы собираетесь пойти по этому пути, одно небольшое замечание: в Python 3 вызов next() для не итератора поднимает TypeError, тогда как эта версия будет поднимать AttributeError вместо.

Редактировать: не важно. Как указывает Стивеха, operator.methodcaller() был введен только в версии 2.6, что является позором.

...