Python关于“解包”生成器的规则是什么

2024-05-14 00:19:49 发布

您现在位置:Python中文网/ 问答频道 /正文

这是一个简单的有界生成器

def bounded_naturals(limit):
    num = 1
    while num <= limit:
        yield num
        num += 1

如果我写

bn_gen = bounded_naturals(3)

bn_gen将是预期的生成器对象

但是如果我写

(a, b, c) = bounded_naturals(3)

abc将分别为1、2和3。这让我觉得很奇怪,因为代码中似乎没有要求生成器生成值的内容。Python规范中是否有需要这种解释的地方

更引人注目的是,如果我写

bn_gen = (a, b, c) = bounded_naturals(3)

我得到了两个结果bn_gen将是一个生成器对象,abc将是1、2和3。我该如何理解发生了什么

最后,如果我写

(a, b) = bounded_naturals(3)

我得到:ValueError: too many values to unpack (expected 2).

如果编译器足够聪明,可以做这些其他的技巧,那么为什么它不足够聪明,在这种情况下,只要求生成器提供所需的元素数量

Python文档中是否有一节解释了所有这些

谢谢


Tags: 对象代码规范内容def地方numgen
2条回答

解包操作任意的可重用项,而不是序列,它通过迭代来实现。当你这样做的时候

(a, b, c) = bounded_naturals(3)

您要求Python迭代bounded_naturals(3),并将结果分配给abc


像这样的多重赋值

bn_gen = (a, b, c) = bounded_naturals(3)

工作原理是将RHS从左到右分配给每个分配目标(不像其他一些语言那样从右到左)。生成器首先被分配到bn_gen,然后被分配到(a, b, c)。请注意,解包会耗尽生成器,因此对bn_gen进行迭代将不会得到任何结果


当你这样做的时候

(a, b) = bounded_naturals(3)

失败与Python不聪明无关。Python不会自动丢弃额外的值,因为这只会隐藏bug。iterable必须提供与解包请求一样多的元素

记住,仅仅因为一些代码可以被赋予非错误含义,并不意味着它应该


所有这些都记录在assignment statement docs

您正在查看的文档是here

assignment_stmt ::=  (target_list "=")+ (starred_expression | yield_expression)
...

Assignment of an object to a target list, optionally enclosed in parentheses or square brackets, is recursively defined as follows.

  • If the target list is a single target with no trailing comma, optionally in parentheses, the object is assigned to that target.
  • Else: The object must be an iterable with the same number of items as there are targets in the target list, and the items are assigned, from left to right, to the corresponding targets.

我想你知道发电机是一个可移植的。让我们看看代码

bn_gen=(a,b,c)=有界自然(3)

这里有两个{}:一个单一目标{}和三个目标{}。由于bn_gen是单个目标,因此bounded_naturals(3)返回的任何内容都将分配给它(在本例中是生成器本身)。然后(a, b, c)被视为具有多个目标的目标列表,RHS(右侧)被“解包”并逐个分配

所以,是的,作为@Pranav Hosangadi noted in comments,你只能什么都不能打开

相关问题 更多 >