newnext.py 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. '''
  2. This module provides a newnext() function in Python 2 that mimics the
  3. behaviour of ``next()`` in Python 3, falling back to Python 2's behaviour for
  4. compatibility if this fails.
  5. ``newnext(iterator)`` calls the iterator's ``__next__()`` method if it exists. If this
  6. doesn't exist, it falls back to calling a ``next()`` method.
  7. For example:
  8. >>> class Odds(object):
  9. ... def __init__(self, start=1):
  10. ... self.value = start - 2
  11. ... def __next__(self): # note the Py3 interface
  12. ... self.value += 2
  13. ... return self.value
  14. ... def __iter__(self):
  15. ... return self
  16. ...
  17. >>> iterator = Odds()
  18. >>> next(iterator)
  19. 1
  20. >>> next(iterator)
  21. 3
  22. If you are defining your own custom iterator class as above, it is preferable
  23. to explicitly decorate the class with the @implements_iterator decorator from
  24. ``future.utils`` as follows:
  25. >>> @implements_iterator
  26. ... class Odds(object):
  27. ... # etc
  28. ... pass
  29. This next() function is primarily for consuming iterators defined in Python 3
  30. code elsewhere that we would like to run on Python 2 or 3.
  31. '''
  32. _builtin_next = next
  33. _SENTINEL = object()
  34. def newnext(iterator, default=_SENTINEL):
  35. """
  36. next(iterator[, default])
  37. Return the next item from the iterator. If default is given and the iterator
  38. is exhausted, it is returned instead of raising StopIteration.
  39. """
  40. # args = []
  41. # if default is not _SENTINEL:
  42. # args.append(default)
  43. try:
  44. try:
  45. return iterator.__next__()
  46. except AttributeError:
  47. try:
  48. return iterator.next()
  49. except AttributeError:
  50. raise TypeError("'{0}' object is not an iterator".format(
  51. iterator.__class__.__name__))
  52. except StopIteration as e:
  53. if default is _SENTINEL:
  54. raise e
  55. else:
  56. return default
  57. __all__ = ['newnext']