Steven D'Aprano wrote: I agree with you that the simple explicit approach is better. Now, to answer the question the OP didn't ask:
> def choose_with_weighting(actions, weights=None): > if weights is None: > weights = [1]*len(actions) # equal weights > # Taken virtually unchanged from your code. > # I hope it does what you want it to do! It probably doesn't. > assert len(weights) == len(actions) > total = sum(weights) > choice = random.randrange(total) > while choice > weights[0]: > choice -= weights[0] > weights.pop(0) > actions.pop(0) > return actions[0] Assume two actions with equal weights [1, 1]. total becomes 2, and choice is either 0 or 1, but never > weights[0]. While this can be fixed by changing the while condition to while choice >= weights[0]: #... I prefer an approach that doesn't destroy the actions and weights lists, something like import bisect def choose_with_weighting(actions, weights=None, acc_weights=None): if acc_weights is None: if weights is None: return random.choice(actions) else: sigma = 0 acc_weights = [] for w in weights: sigma += w acc_weights.append(sigma) return actions[bisect.bisect(acc_weights, random.randrange(acc_weights[-1]))] especially if you prepare the acc_weights list once outside the function. Peter -- http://mail.python.org/mailman/listinfo/python-list