<p>如果您试图创建一个使用累积权重的函数,那么可以按照以下几行进行操作(假设Python 3.6+):</p>
<pre><code>import random
import itertools as it
def wran(*weights):
li=random.choices(list(range(len(weights))),cum_weights=list(it.accumulate(weights)))
return li[0]
</code></pre>
<p>因此,假设您希望<code>[0,1,2,3,4,5]</code>的权重为<code>[50,5,5,5,15,20]</code>(因为它们加起来等于100,可以看作百分比),您可以执行以下操作:</p>
<pre><code>from collections import Counter
>>> t=100000
>>> [(k,'{:.6}%'.format(float(v)/t*100)) for k,v in sorted(Counter(wran(50,5,5,5,15,20) for _ in range(t)).items())]
[(0, '49.926%'), (1, '4.922%'), (2, '5.015%'), (3, '5.067%'), (4, '15.125%'), (5, '19.945%')]
</code></pre>
<p>接近假定的百分比。你知道吗</p>
<hr/>
<p>如果要在Python 3.6+以外的Python上执行此操作,可以生成列表累积和的元组,然后使用<code>bisect</code>获取随机数在该元组列表中的位置索引:</p>
<pre><code>import bisect
def wran(*weights):
totalWeight = sum(weights)
randomInt = random.randint(1, totalWeight)
li=[(sum(weights[0:i]),sum(weights[0:i+1])) for i in range(len(weights))]
return bisect.bisect_left(li,(randomInt,))-1
</code></pre>
<p>测试:</p>
<pre><code>>>> [(k,'{:.6}%'.format(float(v)/t*100)) for k,v in sorted(Counter(wran(50,5,5,5,20,5,5,5) for _ in range(t)).items())]
[(0, '49.943%'), (1, '4.979%'), (2, '5.048%'), (3, '4.968%'), (4, '20.06%'), (5, '5.059%'), (6, '4.954%'), (7, '4.989%')]
</code></pre>
<p>与最初发布的功能相比:</p>
<pre><code>>>> [(k,'{:.6}%'.format(float(v)/t*100)) for k,v in sorted(Counter(weighted_random(50,5,5,5,20,5,5,5) for _ in range(t)).items())]
[(0, '49.986%'), (1, '5.203%'), (2, '4.962%'), (3, '4.998%'), (4, '19.977%'), (5, '5.004%'), (6, '4.986%'), (7, '4.884%')]
</code></pre>