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

Rus*_*ott 3 python

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

def bounded_naturals(limit):
    num = 1
    while num <= limit:
        yield num
        num += 1
Run Code Online (Sandbox Code Playgroud)

如果我写

bn_gen = bounded_naturals(3)

Run Code Online (Sandbox Code Playgroud)

bn_gen 将是预期的生成器对象。

但是如果我写

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

Run Code Online (Sandbox Code Playgroud)

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

更惊人的是,如果我写

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

Run Code Online (Sandbox Code Playgroud)

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

最后,如果我写

(a, b) = bounded_naturals(3)

Run Code Online (Sandbox Code Playgroud)

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

如果编译器足够聪明来执行这些其他技巧,为什么在这种情况下只要求生成器提供所需的元素数量还不够聪明?

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

谢谢。

use*_*ica 5

解包对任意可迭代对象进行操作,而不是序列,它通过迭代来实现。当你做

(a, b, c) = bounded_naturals(3)
Run Code Online (Sandbox Code Playgroud)

你问的Python遍历bounded_naturals(3)和结果分配到abc


一个多重赋值像

bn_gen = (a, b, c) = bounded_naturals(3)
Run Code Online (Sandbox Code Playgroud)

由左到右(分配RHS每个分配目标的工作从右到左像一些其他语言)。生成器首先分配给bn_gen,然后分配给(a, b, c)。请注意,拆包会耗尽生成器,因此迭代bn_gen不会给您任何结果。


当你做

(a, b) = bounded_naturals(3)
Run Code Online (Sandbox Code Playgroud)

失败与 Python 不聪明无关。Python 不会默默地丢弃额外的值,因为这只会隐藏错误。迭代必须提供与解包请求一样多的元素。

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


所有这些都记录在赋值语句文档中