[英]Getting 1 number from 2 ranges with choice() and randint()
我有一段代码
import random as r
value = r.choice(r.randint(10, 30), r.randint(50, 100))
print (value)
为什么它给我以下错误,我应该如何解决它?
TypeError: choice() takes 2 positional arguments but 3 were given
choice
需要一系列项目可供选择,而不是可变参数。 包装 arguments 以创建一个匿名tuple
或list
,它会起作用,改变:
value = r.choice(r.randint(10, 30), r.randint(50, 100))
至:
value = r.choice((r.randint(10, 30), r.randint(50, 100))) # Tuple
value = r.choice([r.randint(10, 30), r.randint(50, 100)]) # List
random.choice
接受单个序列。 对于如何生成所需数字,您有几个选择。
要修复直接错误,请将输入设为序列:
value = r.choice([r.randint(10, 30), r.randint(50, 100)])
这不是一个很好的解决方案,因为它会生成两个数字,这很浪费。 此外,生成的分布取决于范围的大小,这可能是不正确的。
解决此问题的更通用方法是生成一个数字并将 map 生成到您想要的范围:
v = r.randint(0, 21 + 51)
value = v + 10 if v <= 20 else v - 21 + 50
如果要将输入指定为范围并在所有范围内获得均匀分布,则可以这样概括:
def from_ranges(*ranges):
n = sum(map(len, ranges))
v = random.randrange(n)
for range in ranges:
k = len(range)
if v < k:
return range[v]
v -= k
这很好,因为范围是不占用大量空间的小对象,但在您可以指定的内容方面为您提供了很大的灵活性。
对于您问题中的示例,您可以将 function 称为
>>> from_ranges(range(10, 31), range(50, 101))
您还可以通过将长度累加到累积和中来消除最终的线性搜索,以支持二进制搜索:
from bisect import bisect
from itertools import accumulate
from random import randrange
def from_ranges(*ranges):
lengths = list(accumulate(map(len, ranges)))
v = randrange(lengths[-1])
r = bisect(lengths, v)
offset = lengths[r - 1] if r > 0 else 0
return ranges[r][v - offset]
如果您要在生成随机数之前记住累积,此解决方案会更快。 否则,它与第一个解决方案相比几乎没有优势。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.