4

我有以下代码:

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

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

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

for c in hmm():
    print(c)

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

0
1
1
0
1
1

...等等。此外,有没有办法将其编写为生成器表达式以获得与后者相同的结果?

4

1 回答 1

11

yield是一个表达式,它的值是用 . 发送到生成器的任何值send。如果没有发送任何内容,则值为yieldNone。在您的示例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)

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

于 2014-11-17T19:01:16.573 回答