Взвешенная случайная выборка в питоне

Я ищу разумное определение функцииweighted_sample это не возвращает только один случайный индекс для списка заданных весов (который был бы что-то вроде

def weighted_choice(weights, random=random):
    """ Given a list of weights [w_0, w_1, ..., w_n-1],
        return an index i in range(n) with probability proportional to w_i. """
    rnd = random.random() * sum(weights)
    for i, w in enumerate(weights):
        if w<0:
            raise ValueError("Negative weight encountered.")
        rnd -= w
        if rnd < 0:
            return i
    raise ValueError("Sum of weights is not positive")

дать категорическое распределение с постоянными весами), но случайная выборкаk&nbsp;из тех,без замены, как толькоrandom.sample&nbsp;ведет себя по сравнению сrandom.choice.

Как толькоweighted_choice&nbsp;можно записать как

lambda weights: random.choice([val for val, cnt in enumerate(weights)
    for i in range(cnt)])

weighted_sample&nbsp;может быть написано как

lambda weights, k: random.sample([val for val, cnt in enumerate(weights)
    for i in range(cnt)], k)

но я хотел бы получить решение, которое не требует от меня распутывания весов в (возможно, огромный) список.

Редактировать: Если есть какие-либо хорошие алгоритмы, которые возвращают мне гистограмму / список частот (в том же формате, что и аргументweights) вместо последовательности индексов это также было бы очень полезно.