【问题标题】:Why does `yield from` in a generator expression yield `None`s?为什么生成器表达式中的 `yield from` 会产生 `None`s?
【发布时间】:2015-01-14 18:50:03
【问题描述】:

我有以下代码:

import itertools
for c in ((yield from bin(n)[2:]) for n in range(10)):
    print(c)

输出是:

 0
 None
 1
 None
 1
 0 
 None
 1
 1
 None

...等为什么会出现Nones?如果我有:

def hmm():
 for n in range(10):
     yield from bin(n)[2:]

for c in hmm():
    print(c)

然后我得到了我所期望的:

0
1
1
0
1
1

...等等。另外,有没有办法把它写成生成器表达式以获得与后者相同的结果?

【问题讨论】:

  • 最好将您的示例更改为不使用无限循环的示例。为什么不将itertools.count 更改为range(10) 之类的?
  • 来自docs:“此外,允许子生成器返回一个值,并且该值可供委托生成器使用。”
  • 在你的第一个代码中,你混合了 python2 和 3 特定语法,你应该删除 print 语句并使其成为函数调用
  • @LudovicViaud:谢谢,已修复
  • @BrenBarn:那么我不一定需要发电机!我的用例是专门制作一个无限生成器

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


【解决方案1】:

yield 是一个表达式,它的值是用send 发送到生成器的任何值。如果没有发送任何内容,yield 的值为 None。在您的示例中,yield from 产生列表中的值,但 yield from 表达式本身的值是 None,它在封闭生成器表达式的每次迭代中产生(即,range(10) 的每个值)。

你的例子相当于:

def hmm():
    for n in range(10):
        yield (yield from bin(n)[2:])

for item in hmm():
    print(item)

注意额外的yield

如果你尝试在生成器表达式中使用yield,你总会遇到这个问题,因为生成器表达式已经产生了它的目标值,所以如果你添加一个显式的yield,你就是在添加一个额外的表达式( yield 表达式),其值也将在生成器中输出。换句话说,像(x for x in range(5)) 这样的东西已经产生了range(5) 中的数字;如果您执行((yield x) for x in range(5)) 之类的操作,除了数字之外,您还将获得yield 表达式的值。

据我所知,没有办法使用生成器理解来获得简单的yield from 行为(没有额外的无)。对于您的情况,我认为您可以使用itertools.chain.from_iterable 实现您想要的:

for c in itertools.chain.from_iterable(bin(n)[2:] for n in range(10)):
    print(c)

(编辑:我意识到您可以通过使用嵌套的for 子句在生成器理解中获得yield from 行为:x for n in range(10) for x in bin(n)[2:]。但是,我认为这并不比使用itertools.chain 更具可读性。 )

【讨论】:

    猜你喜欢
    • 2017-09-09
    • 2020-05-25
    • 2016-12-02
    • 2018-07-29
    • 2015-03-14
    • 2017-12-16
    • 2017-11-18
    相关资源
    最近更新 更多