import random


def rand_iterable(it, len_it=None):
    """
    Choose a uniformly random value from the given iterable.  If len(it) is
    available, len_it may be None.  Otherwise, len_it must be provided as the
    "length" of the given iterable (the number of values which will be
    produced).

    random.choice() seems to require a sequence (needs indexed access), so it
    doesn't work with things like sets.

    :param it: The iterable
    :param len_it: The length of it, or None to obtain the length via len().
    :return: A random value from it
    """
    if len_it is None:
        len_it = len(it)

    for i, val in enumerate(it):
        if random.random() < 1.0 / (len_it - i):
            return val

    raise Exception("Iterable was empty!")