from moreitertools 9 0 if iterable has only one item return it if it has zero items return default if it has more than one item raise the exception given by toolong which is valueerror by default only default missing missing only1 1 only1 2 doctest ignoreexceptiondetail traceback most recent call last valueerror expected exactly one item in iterable but got 1 2 and perhaps more only1 2 toolongtypeerror doctest ignoreexceptiondetail traceback most recent call last typeerror note that func only attempts to advance iterable twice to ensure there is only one item see func spy or func peekable to check iterable contents less destructively from more_itertools 9 0 if iterable has only one item return it if it has zero items return default if it has more than one item raise the exception given by too_long which is valueerror by default only default missing missing only 1 1 only 1 2 doctest ignore_exception_detail traceback most recent call last valueerror expected exactly one item in iterable but got 1 2 and perhaps more only 1 2 too_long typeerror doctest ignore_exception_detail traceback most recent call last typeerror note that func only attempts to advance iterable twice to ensure there is only one item see func spy or func peekable to check iterable contents less destructively
def only(iterable, default=None, too_long=None):
    
    it = iter(iterable)
    first_value = next(it, default)

    try:
        second_value = next(it)
    except StopIteration:
        pass
    else:
        msg = (
            'Expected exactly one item in iterable, but got {!r}, {!r}, '
            'and perhaps more.'.format(first_value, second_value)
        )
        raise too_long or ValueError(msg)

    return first_value