decorator and API
Peter Otten
__peter__ at web.de
Thu Sep 18 05:32:47 EDT 2008
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
More information about the Python-list
mailing list