_itertools.py 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738
  1. # from more_itertools 9.0
  2. def only(iterable, default=None, too_long=None):
  3. """If *iterable* has only one item, return it.
  4. If it has zero items, return *default*.
  5. If it has more than one item, raise the exception given by *too_long*,
  6. which is ``ValueError`` by default.
  7. >>> only([], default='missing')
  8. 'missing'
  9. >>> only([1])
  10. 1
  11. >>> only([1, 2]) # doctest: +IGNORE_EXCEPTION_DETAIL
  12. Traceback (most recent call last):
  13. ...
  14. ValueError: Expected exactly one item in iterable, but got 1, 2,
  15. and perhaps more.'
  16. >>> only([1, 2], too_long=TypeError) # doctest: +IGNORE_EXCEPTION_DETAIL
  17. Traceback (most recent call last):
  18. ...
  19. TypeError
  20. Note that :func:`only` attempts to advance *iterable* twice to ensure there
  21. is only one item. See :func:`spy` or :func:`peekable` to check
  22. iterable contents less destructively.
  23. """
  24. it = iter(iterable)
  25. first_value = next(it, default)
  26. try:
  27. second_value = next(it)
  28. except StopIteration:
  29. pass
  30. else:
  31. msg = (
  32. 'Expected exactly one item in iterable, but got {!r}, {!r}, '
  33. 'and perhaps more.'.format(first_value, second_value)
  34. )
  35. raise too_long or ValueError(msg)
  36. return first_value