【问题标题】:Difference between `yield from foo()` and `for x in foo(): yield x``yield from foo()` 和 `for x in foo() 之间的区别:yield x`
【发布时间】:2014-11-11 11:48:08
【问题描述】:

在 Python 中,yield from 的大多数例子都用这样的说法来解释它

yield from foo()

类似于

for x in foo(): yield x

另一方面,它似乎并不完全相同,而且其中包含一些魔法。我对使用一个我不理解的魔法函数感到有点不安。对于yield from 的魔力,我必须了解些什么才能避免陷入魔力会发生我没想到的事情的情况?魔法有什么好处,我应该知道?

【问题讨论】:

标签: python python-3.x generator yield yield-from


【解决方案1】:

foo() 返回一个常规迭代时,两者是等价的。当foo() 也是一个生成器时,“魔法”就开始发挥作用了。在那一刻,yield from foo()for x in foo(): yield x 的情况大不相同。

生成器也可以发送数据,使用generator.send() method。当您使用for 循环时,yield x 表达式“接收”发送的数据; foo() 生成器永远不会看到这个。但是当您使用yield from 时,发送的数据会直接发送到委托生成器当前暂停的yield 表达式。换句话说,yield from 传递发送的数据,以便委托的生成器可以接收它。

您还可以在生成器中引发异常,使用generator.throw();对于for 循环情况,异常从yield x 行引发,而yield from 则再次传递异常;而是在 foo() 内部引发异常。

这意味着yield from本质上在委托迭代期间替换了当前生成器。

委托生成器还可以与父生成器通信,完成后,引发的StopIteration 异常的.value 属性将作为yield from 表达式的值返回。您可以通过在委托给foo() 生成器中使用return <expression> 来设置该异常的值,或者您可以显式使用raise StopIteration(<expression>)

yield from 被引入到带有PEP 380: Syntax for Delegating to a Subgenerator 的语言中。

【讨论】:

  • +1 用于简单的解释。 yield from 允许您在不更改代码行为的情况下将生成器重构为多个函数(尽管据我所知嵌套生成器仍未优化,例如,O(n*k) 行为是可能的,如果您正在实现一个幂集而不是O(n) 其中n=2**k)。
  • 这确实为您的答案奠定了基础:“当foo() 返回一个常规迭代时,两者是等价的。当foo() 也是一个生成器时,“魔法”就会发挥作用." 想委托给另一个生成器?使用yield from
猜你喜欢
  • 2011-05-19
  • 1970-01-01
  • 1970-01-01
  • 2018-09-25
  • 2016-09-08
  • 2018-01-19
  • 2016-12-01
  • 2017-07-04
  • 2016-09-09
相关资源
最近更新 更多