Eu precisava escrever uma versão ponderada do random.choice (cada elemento da lista tem uma probabilidade diferente de ser selecionado). Isto é o que eu vim com:
def weightedChoice(choices):
"""Like random.choice, but each element can have a different chance of
being selected.
choices can be any iterable containing iterables with two items each.
Technically, they can have more than two items, the rest will just be
ignored. The first item is the thing being chosen, the second item is
its weight. The weights can be any numeric values, what matters is the
relative differences between them.
"""
space = {}
current = 0
for choice, weight in choices:
if weight > 0:
space[current] = choice
current += weight
rand = random.uniform(0, current)
for key in sorted(space.keys() + [current]):
if rand < key:
return choice
choice = space[key]
return None
Essa função me parece excessivamente complexa e feia. Espero que todos aqui possam oferecer algumas sugestões para aprimorá-lo ou maneiras alternativas de fazer isso. A eficiência não é tão importante para mim quanto a limpeza e a legibilidade do código.
random.choices
para chamadas individuais. Se você precisar de muitos resultados aleatórios, é realmente importante selecioná-los todos de uma vez, ajustandonumber_of_items_to_pick
. Se você fizer isso, é uma ordem de magnitude mais rápida.