为了账号安全,请及时绑定邮箱和手机立即绑定

从 2 个范围中获取 1 个数字,其中包含选择()和兰丁()

从 2 个范围中获取 1 个数字,其中包含选择()和兰丁()

婷婷同学_ 2022-09-27 16:14:39
我有一个代码块import random as rvalue = r.choice(r.randint(10, 30), r.randint(50, 100))print (value)为什么它给我以下错误,我应该如何解决它?TypeError: choice() takes 2 positional arguments but 3 were given 
查看完整描述

2 回答

?
尚方宝剑之说

TA贡献1788条经验 获得超4个赞

choice需要一系列项目可供选择,而不是变量。包装参数以匿名或它将起作用,更改:tuplelist


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


查看完整回答
反对 回复 2022-09-27
?
陪伴而非守候

TA贡献1757条经验 获得超8个赞

随机选择接受单个序列。关于如何生成所需的数字,您有几个选择。


要修复即时错误,请将输入设置为序列:


value = r.choice([r.randint(10, 30), r.randint(50, 100)])

这不是一个很好的解决方案,因为它会生成两个数字,这是浪费的。此外,生成的分布以范围的大小为条件,这可能是不正确的。


解决此问题的更一般方法是生成单个数字并将其映射到所需的范围:


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

这很好,因为范围是小对象,不占用太多空间,但在可以指定的内容方面允许您有很大的灵活性。


对于您问题中的示例,您可以将该函数称为


>>> 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]

如果要在生成随机数之前记住累积,则此解决方案会更快。否则,与第一种解决方案相比,它几乎没有优势。


查看完整回答
反对 回复 2022-09-27
  • 2 回答
  • 0 关注
  • 84 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信